mirror of
https://github.com/unraid/api.git
synced 2026-01-08 09:39:49 -06:00
feat: fix storybook config
This commit is contained in:
16
pnpm-lock.yaml
generated
16
pnpm-lock.yaml
generated
@@ -790,6 +790,9 @@ importers:
|
||||
postcss:
|
||||
specifier: ^8.4.49
|
||||
version: 8.5.3
|
||||
postcss-import:
|
||||
specifier: ^16.1.0
|
||||
version: 16.1.0(postcss@8.5.3)
|
||||
prettier:
|
||||
specifier: 3.5.3
|
||||
version: 3.5.3
|
||||
@@ -9707,6 +9710,12 @@ packages:
|
||||
peerDependencies:
|
||||
postcss: ^8.0.0
|
||||
|
||||
postcss-import@16.1.0:
|
||||
resolution: {integrity: sha512-7hsAZ4xGXl4MW+OKEWCnF6T5jqBw80/EE9aXg1r2yyn1RsVEU8EtKXbijEODa+rg7iih4bKf7vlvTGYR4CnPNg==}
|
||||
engines: {node: '>=18.0.0'}
|
||||
peerDependencies:
|
||||
postcss: ^8.0.0
|
||||
|
||||
postcss-js@4.0.1:
|
||||
resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==}
|
||||
engines: {node: ^12 || ^14 || >= 16}
|
||||
@@ -22577,6 +22586,13 @@ snapshots:
|
||||
read-cache: 1.0.0
|
||||
resolve: 1.22.10
|
||||
|
||||
postcss-import@16.1.0(postcss@8.5.3):
|
||||
dependencies:
|
||||
postcss: 8.5.3
|
||||
postcss-value-parser: 4.2.0
|
||||
read-cache: 1.0.0
|
||||
resolve: 1.22.10
|
||||
|
||||
postcss-js@4.0.1(postcss@8.5.3):
|
||||
dependencies:
|
||||
camelcase-css: 2.0.1
|
||||
|
||||
3
unraid-ui/.gitignore
vendored
3
unraid-ui/.gitignore
vendored
@@ -1,2 +1,3 @@
|
||||
!.env.development
|
||||
dist-wc/
|
||||
dist-wc/
|
||||
.storybook/static/*
|
||||
@@ -1,26 +1,22 @@
|
||||
import { dirname, join } from "path";
|
||||
import type { StorybookConfig } from "@storybook/vue3-vite";
|
||||
|
||||
import { dirname, join } from 'path';
|
||||
import type { StorybookConfig } from '@storybook/vue3-vite';
|
||||
|
||||
const config: StorybookConfig = {
|
||||
stories: ["../stories/**/*.stories.@(js|jsx|ts|tsx)"],
|
||||
addons: [
|
||||
"@storybook/addon-links",
|
||||
"@storybook/addon-essentials",
|
||||
"@storybook/addon-interactions"
|
||||
],
|
||||
stories: ['../stories/**/*.stories.@(js|jsx|ts|tsx)'],
|
||||
addons: ['@storybook/addon-links', '@storybook/addon-essentials', '@storybook/addon-interactions'],
|
||||
framework: {
|
||||
name: "@storybook/vue3-vite",
|
||||
name: '@storybook/vue3-vite',
|
||||
options: {
|
||||
docgen: "vue-component-meta",
|
||||
docgen: 'vue-component-meta',
|
||||
},
|
||||
},
|
||||
core: {
|
||||
builder: "@storybook/builder-vite",
|
||||
builder: '@storybook/builder-vite',
|
||||
},
|
||||
docs: {
|
||||
autodocs: "tag",
|
||||
autodocs: 'tag',
|
||||
},
|
||||
staticDirs: ['./static'],
|
||||
async viteFinal(config) {
|
||||
return {
|
||||
...config,
|
||||
@@ -49,4 +45,4 @@ const config: StorybookConfig = {
|
||||
},
|
||||
};
|
||||
|
||||
export default config;
|
||||
export default config;
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import type { Preview } from '@storybook/vue3';
|
||||
import '../src/styles/globals.css';
|
||||
import { registerAllComponents } from '../src/register';
|
||||
import '@/styles/index.css';
|
||||
|
||||
registerAllComponents({});
|
||||
registerAllComponents({
|
||||
pathToSharedCss: '/index.css',
|
||||
});
|
||||
|
||||
const preview: Preview = {
|
||||
parameters: {
|
||||
@@ -18,9 +20,11 @@ const preview: Preview = {
|
||||
decorators: [
|
||||
(story) => ({
|
||||
components: { story },
|
||||
|
||||
template: `
|
||||
<div>
|
||||
<div id="modals"></div>
|
||||
<uui-modals></uui-modals>
|
||||
|
||||
<story />
|
||||
</div>
|
||||
`,
|
||||
@@ -28,4 +32,4 @@ const preview: Preview = {
|
||||
],
|
||||
};
|
||||
|
||||
export default preview;
|
||||
export default preview;
|
||||
@@ -34,7 +34,10 @@
|
||||
"preunraid:deploy": "pnpm build:wc",
|
||||
"unraid:deploy": "just deploy",
|
||||
"// Storybook": "",
|
||||
"prestorybook": "pnpm storybook:css",
|
||||
"storybook": "storybook dev -p 6006",
|
||||
"storybook:css": "node scripts/build-style.mjs",
|
||||
"prebuild-storybook": "pnpm storybook:css",
|
||||
"build-storybook": "storybook build"
|
||||
},
|
||||
"peerDependencies": {
|
||||
@@ -89,6 +92,7 @@
|
||||
"eslint-plugin-vue": "^10.0.0",
|
||||
"happy-dom": "^17.0.0",
|
||||
"postcss": "^8.4.49",
|
||||
"postcss-import": "^16.1.0",
|
||||
"prettier": "3.5.3",
|
||||
"prettier-plugin-tailwindcss": "^0.6.11",
|
||||
"rimraf": "^6.0.1",
|
||||
|
||||
30
unraid-ui/scripts/build-style.mjs
Normal file
30
unraid-ui/scripts/build-style.mjs
Normal file
@@ -0,0 +1,30 @@
|
||||
import fs from 'fs/promises';
|
||||
import autoprefixer from 'autoprefixer';
|
||||
import postcss from 'postcss';
|
||||
import postcssImport from 'postcss-import';
|
||||
import tailwindcss from 'tailwindcss';
|
||||
|
||||
/**
|
||||
* Helper script for storybook to build the CSS file for the components. This is used to ensure that modals render using the shadow styles.
|
||||
*/
|
||||
|
||||
process.env.VITE_TAILWIND_BASE_FONT_SIZE = 16;
|
||||
|
||||
const inputPath = './src/styles/index.css';
|
||||
const outputPath = './.storybook/static/index.css'; // served from root: /index.css
|
||||
|
||||
const css = await fs.readFile(inputPath, 'utf8');
|
||||
|
||||
const result = await postcss([
|
||||
postcssImport(),
|
||||
tailwindcss({ config: './tailwind.config.ts' }),
|
||||
autoprefixer(),
|
||||
]).process(css, {
|
||||
from: inputPath,
|
||||
to: outputPath,
|
||||
});
|
||||
|
||||
await fs.mkdir('./.storybook/static', { recursive: true });
|
||||
await fs.writeFile(outputPath, result.css);
|
||||
|
||||
console.log('✅ CSS built for Storybook:', outputPath);
|
||||
@@ -18,3 +18,4 @@ export * from '@/components/common/tooltip';
|
||||
export * from '@/components/common/toast';
|
||||
export * from '@/components/common/popover';
|
||||
export * from '@/components/brand';
|
||||
export * from '@/components/modals';
|
||||
@@ -5,15 +5,19 @@ import type { ComboboxContentEmits, ComboboxContentProps } from 'reka-ui';
|
||||
import { ComboboxContent, ComboboxPortal, ComboboxViewport, useForwardPropsEmits } from 'reka-ui';
|
||||
import { computed, type HTMLAttributes } from 'vue';
|
||||
|
||||
const props = withDefaults(defineProps<ComboboxContentProps & { class?: HTMLAttributes['class'] }>(), {
|
||||
position: 'popper',
|
||||
align: 'center',
|
||||
sideOffset: 4,
|
||||
defineOptions({
|
||||
inheritAttrs: false,
|
||||
});
|
||||
const emits = defineEmits<ComboboxContentEmits>();
|
||||
|
||||
const { teleportTarget } = useTeleport();
|
||||
|
||||
const props = withDefaults(defineProps<ComboboxContentProps & { class?: HTMLAttributes['class'] }>(), {
|
||||
forceMount: true,
|
||||
position: 'popper',
|
||||
to: undefined,
|
||||
});
|
||||
const emits = defineEmits<ComboboxContentEmits>();
|
||||
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props;
|
||||
|
||||
@@ -26,7 +30,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);
|
||||
<template>
|
||||
<ComboboxPortal :to="teleportTarget">
|
||||
<ComboboxContent
|
||||
v-bind="forwarded"
|
||||
v-bind="{ ...forwarded, ...$attrs }"
|
||||
:class="
|
||||
cn(
|
||||
'z-50 w-[200px] rounded-md border bg-popover text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
|
||||
|
||||
5
unraid-ui/src/components/modals/ModalTarget.vue
Normal file
5
unraid-ui/src/components/modals/ModalTarget.vue
Normal file
@@ -0,0 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
</script>
|
||||
<template>
|
||||
<div id="modals"></div>
|
||||
</template>
|
||||
1
unraid-ui/src/components/modals/index.ts
Normal file
1
unraid-ui/src/components/modals/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { default as Modals } from './ModalTarget.vue';
|
||||
@@ -4,12 +4,15 @@ const useTeleport = () => {
|
||||
const teleportTarget = ref<string | HTMLElement>('#modals');
|
||||
|
||||
const determineTeleportTarget = () => {
|
||||
const myModalsComponent = document.querySelector('unraid-modals');
|
||||
const myModalsComponent = document.querySelector('unraid-modals') || document.querySelector('uui-modals');
|
||||
console.log('myModalsComponent', myModalsComponent, 'has shadowRoot', myModalsComponent?.shadowRoot);
|
||||
if (!myModalsComponent?.shadowRoot) return;
|
||||
|
||||
const potentialTarget = myModalsComponent.shadowRoot.querySelector('#modals');
|
||||
if (!potentialTarget) return;
|
||||
|
||||
console.log('potentialTarget', potentialTarget);
|
||||
|
||||
teleportTarget.value = potentialTarget as HTMLElement;
|
||||
console.log('[determineTeleportTarget] teleportTarget', teleportTarget.value);
|
||||
};
|
||||
|
||||
@@ -14,5 +14,3 @@ export { default as tailwindConfig } from '../tailwind.config';
|
||||
|
||||
// Composables
|
||||
export { default as useTeleport } from '@/composables/useTeleport';
|
||||
|
||||
// Additional exports not in components.ts
|
||||
|
||||
6
unraid-ui/src/vite-env.d.ts
vendored
Normal file
6
unraid-ui/src/vite-env.d.ts
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
/// <reference types="vite/client" />
|
||||
|
||||
declare module '*.css?raw' {
|
||||
const content: string;
|
||||
export default content;
|
||||
}
|
||||
89
unraid-ui/stories/components/form/Combobox.stories.ts
Normal file
89
unraid-ui/stories/components/form/Combobox.stories.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
import type { Meta, StoryObj } from '@storybook/vue3';
|
||||
import {
|
||||
Combobox as ComboboxComponent,
|
||||
ComboboxEmpty,
|
||||
ComboboxGroup,
|
||||
ComboboxInput,
|
||||
ComboboxItem,
|
||||
ComboboxList,
|
||||
ComboboxTrigger,
|
||||
} from '../../../src/components/form/combobox';
|
||||
|
||||
const meta = {
|
||||
title: 'Components/Form/Combobox',
|
||||
component: ComboboxComponent,
|
||||
} satisfies Meta<typeof ComboboxComponent>;
|
||||
|
||||
export default meta;
|
||||
|
||||
type Story = StoryObj<typeof meta>;
|
||||
|
||||
export const Combobox: Story = {
|
||||
render: (args) => ({
|
||||
components: {
|
||||
ComboboxComponent,
|
||||
ComboboxTrigger,
|
||||
ComboboxInput,
|
||||
ComboboxList,
|
||||
ComboboxGroup,
|
||||
ComboboxItem,
|
||||
},
|
||||
setup() {
|
||||
return { args };
|
||||
},
|
||||
template: `
|
||||
<ComboboxComponent>
|
||||
<ComboboxTrigger class="w-[180px]">
|
||||
<ComboboxInput placeholder="Select a fruit" />
|
||||
</ComboboxTrigger>
|
||||
<ComboboxList>
|
||||
<ComboboxGroup>
|
||||
<ComboboxItem value="apple">Apple</ComboboxItem>
|
||||
<ComboboxItem value="banana">Banana</ComboboxItem>
|
||||
<ComboboxItem value="orange">Orange</ComboboxItem>
|
||||
<ComboboxItem value="grape">Grape</ComboboxItem>
|
||||
</ComboboxGroup>
|
||||
</ComboboxList>
|
||||
</ComboboxComponent>
|
||||
`,
|
||||
}),
|
||||
};
|
||||
|
||||
export const Grouped: Story = {
|
||||
render: (args) => ({
|
||||
components: {
|
||||
ComboboxComponent,
|
||||
ComboboxTrigger,
|
||||
ComboboxInput,
|
||||
ComboboxList,
|
||||
ComboboxGroup,
|
||||
ComboboxItem,
|
||||
ComboboxEmpty,
|
||||
},
|
||||
setup() {
|
||||
return { args };
|
||||
},
|
||||
template: `
|
||||
<div>
|
||||
<ComboboxComponent>
|
||||
<ComboboxTrigger class="w-[180px]">
|
||||
<ComboboxInput placeholder="Select a food" />
|
||||
</ComboboxTrigger>
|
||||
<ComboboxList>
|
||||
<ComboboxEmpty>No results found</ComboboxEmpty>
|
||||
<ComboboxGroup>
|
||||
<ComboboxItem value="apple">Apple</ComboboxItem>
|
||||
<ComboboxItem value="banana">Banana</ComboboxItem>
|
||||
<ComboboxItem value="grape">Grape</ComboboxItem>
|
||||
</ComboboxGroup>
|
||||
<ComboboxGroup>
|
||||
<ComboboxItem value="carrot">Carrot</ComboboxItem>
|
||||
<ComboboxItem value="potato">Potato</ComboboxItem>
|
||||
<ComboboxItem value="celery">Celery</ComboboxItem>
|
||||
</ComboboxGroup>
|
||||
</ComboboxList>
|
||||
</ComboboxComponent>
|
||||
</div>
|
||||
`,
|
||||
}),
|
||||
};
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
SelectLabel,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from '../../../src/components/form/select';
|
||||
} from '@/components/form/select';
|
||||
|
||||
const meta = {
|
||||
title: 'Components/Form/Select',
|
||||
@@ -67,7 +67,6 @@ export const Grouped: Story = {
|
||||
},
|
||||
template: `
|
||||
<div>
|
||||
<unraid-modals></unraid-modals>
|
||||
<SelectComponent>
|
||||
<SelectTrigger class="w-[180px]">
|
||||
<SelectValue placeholder="Select a food" />
|
||||
|
||||
@@ -11,7 +11,6 @@ const useTeleport = () => {
|
||||
if (!potentialTarget) return;
|
||||
|
||||
teleportTarget.value = potentialTarget;
|
||||
console.log("[determineTeleportTarget] teleportTarget", teleportTarget.value);
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
|
||||
Reference in New Issue
Block a user