feat: add Tailwind scoping plugin and integrate into Vite config (#1722)

- Introduced a new PostCSS plugin, `scopeTailwindToUnapi`, to scope
Tailwind CSS classes to specific elements.
- Updated Vite configuration to include the new PostCSS plugin for CSS
processing.
- Enhanced theme management in the theme store to apply scoped classes
and dynamic CSS variables to multiple targets, including the document
root and elements with the `.unapi` class.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Scoped styling for embedded (.unapi) contexts and a PostCSS plugin to
automate it.
* Theme refresh after mount to propagate CSS variables to embedded
roots.
  * Exposed idempotent restart action for the Unraid API when offline.

* **Bug Fixes**
* Consistent dark mode and theme variable application across main and
embedded views.
  * Interactive element and SSO styles now apply in embedded contexts.
* Simplified changelog iframe with a reliable fallback renderer;
improved logs styling scope.

* **Tests**
* New unit tests for the scoping plugin, changelog iframe, and related
components.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Eli Bosley
2025-09-26 09:56:27 -04:00
committed by GitHub
parent b3ca40c639
commit b7afaf4632
22 changed files with 1089 additions and 301 deletions

View File

@@ -69,8 +69,45 @@ switch ($command) {
response_complete(200, array('result' => $output), $output);
break;
case 'restart':
$lockFilePath = '/var/run/unraid-api-restart.lock';
$lockHandle = @fopen($lockFilePath, 'c');
if ($lockHandle === false) {
response_complete(500, array('error' => 'Unable to open restart lock file'), 'Unable to open restart lock file');
}
// Use a lockfile to avoid concurrently running restart commands
$wouldBlock = null;
error_clear_last();
$acquiredLock = flock($lockHandle, LOCK_EX | LOCK_NB, $wouldBlock);
if (!$acquiredLock) {
if (!empty($wouldBlock)) {
fclose($lockHandle);
response_complete(200, array('success' => true, 'result' => 'Unraid API restart already in progress'), 'Restart already in progress');
}
$lastError = error_get_last();
$errorMessage = 'Unable to acquire restart lock';
if (!empty($lastError['message'])) {
$errorMessage .= ': ' . $lastError['message'];
}
fclose($lockHandle);
response_complete(500, array('error' => $errorMessage), $errorMessage);
}
$pid = getmypid();
if ($pid !== false) {
ftruncate($lockHandle, 0);
fwrite($lockHandle, (string)$pid);
fflush($lockHandle);
}
exec('/etc/rc.d/rc.unraid-api restart 2>&1', $output, $retval);
$output = implode(PHP_EOL, $output);
flock($lockHandle, LOCK_UN);
fclose($lockHandle);
response_complete(200, array('success' => ($retval === 0), 'result' => $output, 'error' => ($retval !== 0 ? $output : null)), $output);
break;
case 'status':
@@ -100,4 +137,4 @@ switch ($command) {
break;
}
exit;
?>
?>