@socprime/react-ui 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (153) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/LICENSE +21 -0
  3. package/README.md +537 -0
  4. package/attack-flow.d.ts +16 -0
  5. package/charts.d.ts +32 -0
  6. package/decorators/index.js +8 -0
  7. package/decorators/withRouter.js +10 -0
  8. package/decorators/withTheme.js +10 -0
  9. package/decorators.d.ts +10 -0
  10. package/domain.d.ts +23 -0
  11. package/editor.d.ts +25 -0
  12. package/index.d.ts +702 -0
  13. package/lib/cn.js +8 -0
  14. package/lib/theme.js +26 -0
  15. package/lib/useFullscreen.js +52 -0
  16. package/lib/useListenOnResizeDebounce.js +22 -0
  17. package/lib/useThemeColors.js +39 -0
  18. package/package.json +113 -0
  19. package/preset/createConfig.js +98 -0
  20. package/preset/createPreview.js +53 -0
  21. package/preset/index.js +6 -0
  22. package/preset/restoreNativeFocus.js +33 -0
  23. package/preset/types.js +0 -0
  24. package/preset.d.ts +27 -0
  25. package/theme-9m7j1UoI.d.ts +5 -0
  26. package/ui/Accordion/Accordion.js +82 -0
  27. package/ui/Accordion/AccordionSection.js +41 -0
  28. package/ui/Accordion/FolderTreeExpandTrigger.js +29 -0
  29. package/ui/Accordion/chevronVariants.js +31 -0
  30. package/ui/Accordion/index.js +16 -0
  31. package/ui/AnimatedDots/AnimatedDots.js +10 -0
  32. package/ui/AnimatedDots/index.js +4 -0
  33. package/ui/Aside/Aside.js +34 -0
  34. package/ui/Aside/index.js +4 -0
  35. package/ui/AttackFlow/AttackFlow.js +9 -0
  36. package/ui/AttackFlow/AttackFlowLayout.js +63 -0
  37. package/ui/AttackFlow/Controls.js +42 -0
  38. package/ui/AttackFlow/Node.js +47 -0
  39. package/ui/AttackFlow/OtherNode.js +44 -0
  40. package/ui/AttackFlow/index.js +4 -0
  41. package/ui/AttackFlow/prependData.js +153 -0
  42. package/ui/AttackFlow/types.js +0 -0
  43. package/ui/AttackFlow/useAttackFlow.js +193 -0
  44. package/ui/Badge/Badge.js +57 -0
  45. package/ui/Badge/index.js +5 -0
  46. package/ui/Button/Button.css +1 -0
  47. package/ui/Button/Button.js +109 -0
  48. package/ui/Button/index.js +5 -0
  49. package/ui/Charts/AreaChartWithGradient.js +79 -0
  50. package/ui/Charts/index.js +4 -0
  51. package/ui/Checkbox/Checkbox.js +31 -0
  52. package/ui/Checkbox/index.js +4 -0
  53. package/ui/ConditionalContent/ConditionalContent.js +10 -0
  54. package/ui/ConditionalContent/index.js +4 -0
  55. package/ui/CorrelationTimer/CorrelationTimer.js +62 -0
  56. package/ui/CorrelationTimer/index.js +4 -0
  57. package/ui/DeleteButtonConfirm/DeleteButtonConfirm.js +65 -0
  58. package/ui/DeleteButtonConfirm/index.js +4 -0
  59. package/ui/Dialog/ConfirmDialog.js +54 -0
  60. package/ui/Dialog/DefaultDialog.js +82 -0
  61. package/ui/Dialog/Dialog.js +120 -0
  62. package/ui/Dialog/index.js +32 -0
  63. package/ui/Dropdown/Dropdown.js +204 -0
  64. package/ui/Dropdown/DropdownsCheckbox.js +102 -0
  65. package/ui/Dropdown/DropdownsSelect.js +97 -0
  66. package/ui/Dropdown/index.js +38 -0
  67. package/ui/Editor/Editor.js +97 -0
  68. package/ui/Editor/index.js +4 -0
  69. package/ui/Editor/monacoSetup.js +38 -0
  70. package/ui/Editor/theme.js +50 -0
  71. package/ui/Editor/types.js +0 -0
  72. package/ui/EmptyState/EmptyState.js +26 -0
  73. package/ui/EmptyState/index.js +4 -0
  74. package/ui/Field/Field.js +204 -0
  75. package/ui/Field/index.js +24 -0
  76. package/ui/HelperText/HelperText.js +7 -0
  77. package/ui/HelperText/index.js +4 -0
  78. package/ui/Input/Input.js +40 -0
  79. package/ui/Input/index.js +4 -0
  80. package/ui/InputNumber/InputNumber.js +90 -0
  81. package/ui/InputNumber/index.js +4 -0
  82. package/ui/InputPassword/InputPassword.js +30 -0
  83. package/ui/InputPassword/index.js +4 -0
  84. package/ui/Label/Label.js +13 -0
  85. package/ui/Label/LabelInfo.js +14 -0
  86. package/ui/Label/index.js +6 -0
  87. package/ui/MultiSelect/MultiSelect.js +163 -0
  88. package/ui/MultiSelect/index.js +4 -0
  89. package/ui/PageHeader/PageHeader.js +51 -0
  90. package/ui/PageHeader/index.js +4 -0
  91. package/ui/Pagination/Pagination.js +97 -0
  92. package/ui/Pagination/PaginationWrap.js +149 -0
  93. package/ui/Pagination/index.js +20 -0
  94. package/ui/RadioGroup/RadioGroup.js +45 -0
  95. package/ui/RadioGroup/index.js +5 -0
  96. package/ui/ScrollArea/ScrollArea.js +57 -0
  97. package/ui/ScrollArea/index.js +5 -0
  98. package/ui/SearchInput/SearchInput.js +38 -0
  99. package/ui/SearchInput/index.js +4 -0
  100. package/ui/SearchInputFields/SearchInputFields.js +53 -0
  101. package/ui/SearchInputFields/index.js +4 -0
  102. package/ui/Select/Select.js +155 -0
  103. package/ui/Select/SelectDefault.js +43 -0
  104. package/ui/Select/index.js +26 -0
  105. package/ui/Separator/Separator.js +26 -0
  106. package/ui/Separator/index.js +4 -0
  107. package/ui/Severity/Severity.js +11 -0
  108. package/ui/Severity/index.js +4 -0
  109. package/ui/Severity/utils.js +53 -0
  110. package/ui/Skeleton/Skeleton.js +25 -0
  111. package/ui/Skeleton/index.js +5 -0
  112. package/ui/Slider/Slider.js +50 -0
  113. package/ui/Slider/index.js +4 -0
  114. package/ui/Spinner/Spinner.js +21 -0
  115. package/ui/Spinner/index.js +5 -0
  116. package/ui/SpinnerSquare/SpinnerSquare.css +1 -0
  117. package/ui/SpinnerSquare/SpinnerSquare.js +22 -0
  118. package/ui/SpinnerSquare/index.js +4 -0
  119. package/ui/StatisticCard/StatisticCard.js +27 -0
  120. package/ui/StatisticCard/index.js +4 -0
  121. package/ui/StatisticCard/types.js +0 -0
  122. package/ui/Suggestions/Suggestions.js +244 -0
  123. package/ui/Suggestions/index.js +4 -0
  124. package/ui/Switch/Switch.js +64 -0
  125. package/ui/Switch/index.js +4 -0
  126. package/ui/SyncProcessBar/SyncProcessBar.js +14 -0
  127. package/ui/SyncProcessBar/index.js +4 -0
  128. package/ui/Table/GroupHeaderRow.js +36 -0
  129. package/ui/Table/RowGrouped.js +19 -0
  130. package/ui/Table/ServerGroupedTableBody.js +89 -0
  131. package/ui/Table/SortableHeader.js +46 -0
  132. package/ui/Table/Table.js +110 -0
  133. package/ui/Table/TableWrap.js +124 -0
  134. package/ui/Table/columnStyle.js +14 -0
  135. package/ui/Table/index.js +28 -0
  136. package/ui/Tabs/Tabs.js +76 -0
  137. package/ui/Tabs/index.js +4 -0
  138. package/ui/TextTruncate/TextTruncate.js +107 -0
  139. package/ui/TextTruncate/index.js +4 -0
  140. package/ui/Textarea/Textarea.js +20 -0
  141. package/ui/Textarea/index.js +4 -0
  142. package/ui/ThemeToggle/ThemeToggle.js +23 -0
  143. package/ui/ThemeToggle/index.js +4 -0
  144. package/ui/Toast/Toast.js +23 -0
  145. package/ui/Toast/index.js +4 -0
  146. package/ui/Tooltip/Tooltip.js +17 -0
  147. package/ui/Tooltip/TooltipLayout.js +60 -0
  148. package/ui/Tooltip/index.js +14 -0
  149. package/ui/TreeGuide/TreeGuide.js +23 -0
  150. package/ui/TreeGuide/index.js +5 -0
  151. package/ui/entries/charts.js +2 -0
  152. package/ui/entries/domain.js +3 -0
  153. package/ui/index.js +45 -0
package/lib/cn.js ADDED
@@ -0,0 +1,8 @@
1
+ import { clsx } from "clsx";
2
+ import { twMerge } from "tailwind-merge";
3
+ function cn(...inputs) {
4
+ return twMerge(clsx(inputs));
5
+ }
6
+ export {
7
+ cn
8
+ };
package/lib/theme.js ADDED
@@ -0,0 +1,26 @@
1
+ import { useSyncExternalStore } from "react";
2
+ function applyTheme(theme) {
3
+ const root = document.documentElement;
4
+ root.classList.remove("dark", "light");
5
+ root.classList.add(theme);
6
+ root.setAttribute("data-theme", theme);
7
+ }
8
+ function getTheme() {
9
+ const theme = document.documentElement.getAttribute("data-theme");
10
+ return theme === "light" ? "light" : "dark";
11
+ }
12
+ function subscribe(onStoreChange) {
13
+ const observer = new MutationObserver(onStoreChange);
14
+ observer.observe(document.documentElement, {
15
+ attributes: true,
16
+ attributeFilter: ["data-theme"]
17
+ });
18
+ return () => observer.disconnect();
19
+ }
20
+ function useDocumentTheme() {
21
+ return useSyncExternalStore(subscribe, getTheme, () => "dark");
22
+ }
23
+ export {
24
+ applyTheme,
25
+ useDocumentTheme
26
+ };
@@ -0,0 +1,52 @@
1
+ import { useCallback, useEffect, useState } from "react";
2
+ function useFullscreen(element, onFullscreenChange) {
3
+ const [isFullscreen, setIsFullscreen] = useState(false);
4
+ const handleFullscreenChange = useCallback(() => {
5
+ const { fullscreenElement } = document;
6
+ const isCurrentlyFullscreen = !!fullscreenElement;
7
+ setIsFullscreen(isCurrentlyFullscreen);
8
+ onFullscreenChange?.(isCurrentlyFullscreen);
9
+ }, [onFullscreenChange]);
10
+ useEffect(() => {
11
+ document.addEventListener("fullscreenchange", handleFullscreenChange);
12
+ return () => {
13
+ document.removeEventListener("fullscreenchange", handleFullscreenChange);
14
+ };
15
+ }, [handleFullscreenChange]);
16
+ const enterFullscreen = useCallback(async () => {
17
+ if (!element.current) {
18
+ return;
19
+ }
20
+ try {
21
+ await element.current.requestFullscreen();
22
+ } catch (error) {
23
+ console.error(error);
24
+ }
25
+ }, [element]);
26
+ const exitFullscreen = useCallback(async () => {
27
+ if (!document.fullscreenElement) {
28
+ return;
29
+ }
30
+ try {
31
+ await document.exitFullscreen();
32
+ } catch (error) {
33
+ console.error(error);
34
+ }
35
+ }, []);
36
+ const toggleFullscreen = useCallback(async () => {
37
+ if (document.fullscreenElement) {
38
+ await exitFullscreen();
39
+ } else {
40
+ await enterFullscreen();
41
+ }
42
+ }, [enterFullscreen, exitFullscreen]);
43
+ return {
44
+ isFullscreen,
45
+ toggleFullscreen,
46
+ enterFullscreen,
47
+ exitFullscreen
48
+ };
49
+ }
50
+ export {
51
+ useFullscreen
52
+ };
@@ -0,0 +1,22 @@
1
+ import { useEffect } from "react";
2
+ const useListenOnResizeDebounce = (handleResize) => {
3
+ useEffect(() => {
4
+ let resizeTimeout;
5
+ const debouncedResize = () => {
6
+ if (resizeTimeout) {
7
+ clearTimeout(resizeTimeout);
8
+ }
9
+ resizeTimeout = setTimeout(handleResize, 200);
10
+ };
11
+ window.addEventListener("resize", debouncedResize);
12
+ return () => {
13
+ window.removeEventListener("resize", debouncedResize);
14
+ if (resizeTimeout) {
15
+ clearTimeout(resizeTimeout);
16
+ }
17
+ };
18
+ }, [handleResize]);
19
+ };
20
+ export {
21
+ useListenOnResizeDebounce
22
+ };
@@ -0,0 +1,39 @@
1
+ import { useSyncExternalStore } from "react";
2
+ function colorsEqual(a, b) {
3
+ return a.primary === b.primary && a.secondary === b.secondary && a.success === b.success && a.lightBlue === b.lightBlue && a.purple === b.purple && a.default === b.default && a.subdued === b.subdued && a.warning === b.warning && a.critical === b.critical && a.border === b.border;
4
+ }
5
+ let cachedColors = null;
6
+ function getThemeColors() {
7
+ const styles = getComputedStyle(document.documentElement);
8
+ const nextColors = {
9
+ primary: styles.getPropertyValue("--bg-primary").trim(),
10
+ secondary: styles.getPropertyValue("--bg-secondary").trim(),
11
+ success: styles.getPropertyValue("--bg-success").trim(),
12
+ lightBlue: styles.getPropertyValue("--bg-light-blue").trim(),
13
+ purple: styles.getPropertyValue("--bg-purple").trim(),
14
+ default: styles.getPropertyValue("--text-default").trim(),
15
+ subdued: styles.getPropertyValue("--text-subdued").trim(),
16
+ warning: styles.getPropertyValue("--text-warning").trim(),
17
+ critical: styles.getPropertyValue("--text-critical").trim(),
18
+ border: styles.getPropertyValue("--border").trim()
19
+ };
20
+ if (cachedColors && colorsEqual(cachedColors, nextColors)) {
21
+ return cachedColors;
22
+ }
23
+ cachedColors = nextColors;
24
+ return cachedColors;
25
+ }
26
+ function subscribe(onStoreChange) {
27
+ const observer = new MutationObserver(onStoreChange);
28
+ observer.observe(document.documentElement, {
29
+ attributes: true,
30
+ attributeFilter: ["data-theme", "class"]
31
+ });
32
+ return () => observer.disconnect();
33
+ }
34
+ function useThemeColors() {
35
+ return useSyncExternalStore(subscribe, getThemeColors, getThemeColors);
36
+ }
37
+ export {
38
+ useThemeColors
39
+ };
package/package.json ADDED
@@ -0,0 +1,113 @@
1
+ {
2
+ "name": "@socprime/react-ui",
3
+ "version": "0.0.5",
4
+ "description": "SOC Prime React UI component library and Storybook design system.",
5
+ "license": "MIT",
6
+ "engines": {
7
+ "node": ">=20"
8
+ },
9
+ "type": "module",
10
+ "sideEffects": [
11
+ "**/*.css"
12
+ ],
13
+ "main": "./ui/index.js",
14
+ "types": "./index.d.ts",
15
+ "exports": {
16
+ ".": {
17
+ "types": "./index.d.ts",
18
+ "import": "./ui/index.js"
19
+ },
20
+ "./editor": {
21
+ "types": "./editor.d.ts",
22
+ "import": "./ui/Editor/index.js"
23
+ },
24
+ "./charts": {
25
+ "types": "./charts.d.ts",
26
+ "import": "./ui/entries/charts.js"
27
+ },
28
+ "./domain": {
29
+ "types": "./domain.d.ts",
30
+ "import": "./ui/entries/domain.js"
31
+ },
32
+ "./attack-flow": {
33
+ "types": "./attack-flow.d.ts",
34
+ "import": "./ui/AttackFlow/index.js"
35
+ },
36
+ "./preset": {
37
+ "types": "./preset.d.ts",
38
+ "import": "./preset/index.js"
39
+ },
40
+ "./decorators": {
41
+ "types": "./decorators.d.ts",
42
+ "import": "./decorators/index.js"
43
+ },
44
+ "./package.json": "./package.json"
45
+ },
46
+ "peerDependencies": {
47
+ "@monaco-editor/react": "^4.7.0",
48
+ "@storybook/react-vite": "^10.0.0",
49
+ "@tanstack/react-table": "^8.21.0",
50
+ "@xyflow/react": "^12.9.2",
51
+ "dagre": "^0.8.5",
52
+ "monaco-editor": "^0.55.1",
53
+ "react": "^19.0.0",
54
+ "react-dom": "^19.0.0",
55
+ "react-router-dom": "^7.0.0",
56
+ "recharts": "^3.8.1",
57
+ "vite": "^7.0.0",
58
+ "vite-plugin-svgr": "^4.0.0"
59
+ },
60
+ "peerDependenciesMeta": {
61
+ "@monaco-editor/react": {
62
+ "optional": true
63
+ },
64
+ "@storybook/react-vite": {
65
+ "optional": true
66
+ },
67
+ "@xyflow/react": {
68
+ "optional": true
69
+ },
70
+ "dagre": {
71
+ "optional": true
72
+ },
73
+ "monaco-editor": {
74
+ "optional": true
75
+ },
76
+ "recharts": {
77
+ "optional": true
78
+ },
79
+ "vite": {
80
+ "optional": true
81
+ },
82
+ "vite-plugin-svgr": {
83
+ "optional": true
84
+ }
85
+ },
86
+ "dependencies": {
87
+ "@radix-ui/react-accordion": "^1.2.12",
88
+ "@radix-ui/react-checkbox": "^1.3.3",
89
+ "@radix-ui/react-dialog": "^1.1.15",
90
+ "@radix-ui/react-dropdown-menu": "^2.1.16",
91
+ "@radix-ui/react-label": "^2.1.8",
92
+ "@radix-ui/react-navigation-menu": "^1.2.14",
93
+ "@radix-ui/react-popover": "^1.1.15",
94
+ "@radix-ui/react-radio-group": "^1.3.8",
95
+ "@radix-ui/react-scroll-area": "^1.2.10",
96
+ "@radix-ui/react-select": "^2.2.6",
97
+ "@radix-ui/react-separator": "^1.1.8",
98
+ "@radix-ui/react-slider": "^1.3.6",
99
+ "@radix-ui/react-slot": "^1.2.4",
100
+ "@radix-ui/react-switch": "^1.2.6",
101
+ "@radix-ui/react-tabs": "^1.1.13",
102
+ "@radix-ui/react-tooltip": "^1.2.8",
103
+ "class-variance-authority": "^0.7.1",
104
+ "clsx": "^2.1.1",
105
+ "lucide-react": "^0.552.0",
106
+ "motion": "^12.23.24",
107
+ "sonner": "^2.0.7",
108
+ "tailwind-merge": "^3.3.1"
109
+ },
110
+ "publishConfig": {
111
+ "access": "public"
112
+ }
113
+ }
@@ -0,0 +1,98 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import path from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { mergeConfig } from "vite";
5
+ import svgr from "vite-plugin-svgr";
6
+ const PACKAGE_NAME = "@socprime/react-ui";
7
+ function findPackageRoot(startDir) {
8
+ let dir = startDir;
9
+ while (!existsSync(path.join(dir, "package.json"))) {
10
+ const parent = path.dirname(dir);
11
+ if (parent === dir) {
12
+ throw new Error(`Could not locate a package.json above ${startDir}`);
13
+ }
14
+ dir = parent;
15
+ }
16
+ return dir;
17
+ }
18
+ function resolvePackageRoot(explicitPackageRoot) {
19
+ if (explicitPackageRoot) {
20
+ return explicitPackageRoot;
21
+ }
22
+ const presetDir = path.dirname(fileURLToPath(import.meta.url));
23
+ const root = findPackageRoot(presetDir);
24
+ const { name } = JSON.parse(readFileSync(path.join(root, "package.json"), "utf-8"));
25
+ if (name === PACKAGE_NAME) {
26
+ throw new Error(
27
+ `createStorybookConfig(): could not infer "packageRoot" because "${PACKAGE_NAME}/preset" is running from an installed dependency. Pass "packageRoot" explicitly \u2014 the root of your own Storybook package that owns the "stories/" directory.`
28
+ );
29
+ }
30
+ return root;
31
+ }
32
+ function createStorybookConfig(options) {
33
+ const packageRoot = resolvePackageRoot(options.packageRoot);
34
+ const storiesDir = path.join(packageRoot, "stories");
35
+ const stories = [
36
+ path.join(storiesDir, "**/*.stories.@(js|jsx|mjs|ts|tsx)"),
37
+ ...options.extraStories?.map((glob) => path.join(packageRoot, glob)) ?? []
38
+ ];
39
+ return {
40
+ stories,
41
+ addons: ["@storybook/addon-docs", "@storybook/addon-a11y"],
42
+ framework: "@storybook/react-vite",
43
+ features: {
44
+ changeDetection: false,
45
+ sidebarOnboardingChecklist: false,
46
+ menuOnboardingChecklist: false
47
+ },
48
+ staticDirs: [
49
+ {
50
+ from: path.join(options.hostRoot, "public"),
51
+ to: "/"
52
+ }
53
+ ],
54
+ async viteFinal(config) {
55
+ return mergeConfig(config, {
56
+ define: {
57
+ __APP_VERSION__: JSON.stringify(options.appVersion ?? "0.0.0")
58
+ },
59
+ resolve: {
60
+ alias: {
61
+ "@": packageRoot,
62
+ "@storybook-host/theme-entry": options.themeEntry
63
+ }
64
+ },
65
+ plugins: [
66
+ svgr({
67
+ svgrOptions: {
68
+ icon: true
69
+ }
70
+ })
71
+ ],
72
+ css: {
73
+ preprocessorOptions: {
74
+ scss: {
75
+ loadPaths: [options.hostSrcDir],
76
+ additionalData: `@use 'assets/scss/palette' as palette;`
77
+ }
78
+ }
79
+ },
80
+ server: {
81
+ fs: {
82
+ allow: [options.hostRoot, packageRoot]
83
+ }
84
+ },
85
+ worker: {
86
+ format: "es"
87
+ },
88
+ optimizeDeps: {
89
+ include: ["monaco-editor"],
90
+ exclude: ["@monaco-editor/react"]
91
+ }
92
+ });
93
+ }
94
+ };
95
+ }
96
+ export {
97
+ createStorybookConfig
98
+ };
@@ -0,0 +1,53 @@
1
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
+ import { withRouter, withTheme } from "../decorators/index.js";
3
+ import { Toaster } from "../ui/index.js";
4
+ import { restoreNativeFocus } from "./restoreNativeFocus.js";
5
+ function createStorybookPreview() {
6
+ return {
7
+ globalTypes: {
8
+ theme: {
9
+ description: "Host color theme (CSS tokens from theme entry)",
10
+ toolbar: {
11
+ title: "Theme",
12
+ icon: "circlehollow",
13
+ items: [
14
+ { value: "dark", title: "Dark", icon: "moon" },
15
+ { value: "light", title: "Light", icon: "sun" }
16
+ ],
17
+ dynamicTitle: true
18
+ }
19
+ }
20
+ },
21
+ initialGlobals: {
22
+ theme: "dark"
23
+ },
24
+ parameters: {
25
+ layout: "centered",
26
+ controls: {
27
+ matchers: {
28
+ color: /(background|color)$/i,
29
+ date: /Date$/i
30
+ }
31
+ },
32
+ backgrounds: { disable: true },
33
+ a11y: {
34
+ // Fails interaction/test-runner runs when violations are found.
35
+ test: "error"
36
+ }
37
+ },
38
+ decorators: [
39
+ withRouter,
40
+ withTheme,
41
+ (Story) => /* @__PURE__ */ jsxs(Fragment, { children: [
42
+ /* @__PURE__ */ jsx(Story, {}),
43
+ /* @__PURE__ */ jsx(Toaster, {})
44
+ ] })
45
+ ],
46
+ beforeEach() {
47
+ restoreNativeFocus();
48
+ }
49
+ };
50
+ }
51
+ export {
52
+ createStorybookPreview
53
+ };
@@ -0,0 +1,6 @@
1
+ import { createStorybookConfig } from "./createConfig.js";
2
+ import { createStorybookPreview } from "./createPreview.js";
3
+ export {
4
+ createStorybookConfig,
5
+ createStorybookPreview
6
+ };
@@ -0,0 +1,33 @@
1
+ let cachedNativeFocus = null;
2
+ function getNativeFocus() {
3
+ if (cachedNativeFocus) {
4
+ return cachedNativeFocus;
5
+ }
6
+ const iframe = document.createElement("iframe");
7
+ iframe.style.display = "none";
8
+ document.body.appendChild(iframe);
9
+ const contentWindow = iframe.contentWindow;
10
+ if (!contentWindow) {
11
+ throw new Error("Unable to access iframe content window");
12
+ }
13
+ const { focus } = contentWindow.HTMLElement.prototype;
14
+ document.body.removeChild(iframe);
15
+ cachedNativeFocus = focus;
16
+ return focus;
17
+ }
18
+ function restoreNativeFocus() {
19
+ if (typeof HTMLElement === "undefined") {
20
+ return;
21
+ }
22
+ const nativeFocus = getNativeFocus();
23
+ Object.defineProperty(HTMLElement.prototype, "focus", {
24
+ configurable: true,
25
+ writable: true,
26
+ value: function focus(options) {
27
+ return nativeFocus.call(this, options);
28
+ }
29
+ });
30
+ }
31
+ export {
32
+ restoreNativeFocus
33
+ };
File without changes
package/preset.d.ts ADDED
@@ -0,0 +1,27 @@
1
+ import { StorybookConfig, Preview } from '@storybook/react-vite';
2
+
3
+ interface StorybookHostOptions {
4
+ /** Absolute path to the host application root (Vite `server.fs.allow`). */
5
+ hostRoot: string;
6
+ /** Absolute path to the host `src/` directory (Sass load path for palette tokens). */
7
+ hostSrcDir: string;
8
+ /** Absolute path to the host global theme entry SCSS (e.g. `src/index.scss`). */
9
+ themeEntry: string;
10
+ /** Absolute path to the package root where `stories/` lives. Defaults to the preset package root. */
11
+ packageRoot?: string;
12
+ /** Injected as `__APP_VERSION__` in Storybook builds. */
13
+ appVersion?: string;
14
+ /** Additional story globs relative to `packageRoot`. */
15
+ extraStories?: string[];
16
+ }
17
+
18
+ /**
19
+ * Creates a Storybook config for a UI component catalog.
20
+ * Component code under `ui/` must not import from the host `src/` —
21
+ * `@/` resolves only within this package root.
22
+ */
23
+ declare function createStorybookConfig(options: StorybookHostOptions): StorybookConfig;
24
+
25
+ declare function createStorybookPreview(): Preview;
26
+
27
+ export { type StorybookHostOptions, createStorybookConfig, createStorybookPreview };
@@ -0,0 +1,5 @@
1
+ type ThemeName = 'dark' | 'light';
2
+ declare function applyTheme(theme: ThemeName): void;
3
+ declare function useDocumentTheme(): ThemeName;
4
+
5
+ export { type ThemeName as T, applyTheme as a, useDocumentTheme as u };
@@ -0,0 +1,82 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import * as AccordionPrimitive from "@radix-ui/react-accordion";
3
+ import { ChevronDownIcon } from "lucide-react";
4
+ import { cn } from "../../lib/cn.js";
5
+ import {
6
+ accordionChevronVariants,
7
+ resolveAccordionChevronVariant
8
+ } from "./chevronVariants.js";
9
+ const Accordion = ({ children, ...props }) => {
10
+ return /* @__PURE__ */ jsx(AccordionPrimitive.Root, { "data-slot": "accordion", ...props, children });
11
+ };
12
+ const AccordionItem = ({ className, children, ...props }) => {
13
+ return /* @__PURE__ */ jsx(
14
+ AccordionPrimitive.Item,
15
+ {
16
+ "data-slot": "accordion-item",
17
+ className: cn("border-border border-b last:border-b-0", className),
18
+ ...props,
19
+ children
20
+ }
21
+ );
22
+ };
23
+ const AccordionTrigger = ({
24
+ className,
25
+ children,
26
+ chevronPosition,
27
+ chevronVariant,
28
+ ...props
29
+ }) => {
30
+ const resolvedVariant = resolveAccordionChevronVariant(chevronPosition, chevronVariant);
31
+ const showChevron = Boolean(chevronPosition) && resolvedVariant !== "none";
32
+ const isChevronLeft = chevronPosition === "left";
33
+ const variantConfig = resolvedVariant !== "none" ? accordionChevronVariants[resolvedVariant] : void 0;
34
+ const chevron = showChevron ? /* @__PURE__ */ jsx(
35
+ ChevronDownIcon,
36
+ {
37
+ className: cn(
38
+ "text-muted-foreground pointer-events-none size-4 shrink-0 translate-y-0.5 transition-transform duration-200",
39
+ variantConfig?.icon
40
+ )
41
+ }
42
+ ) : null;
43
+ return /* @__PURE__ */ jsx(AccordionPrimitive.Header, { className: "flex", children: /* @__PURE__ */ jsxs(
44
+ AccordionPrimitive.Trigger,
45
+ {
46
+ "data-slot": "accordion-trigger",
47
+ className: cn(
48
+ "group/accordion-trigger flex flex-1 items-start gap-2 px-2 py-4 text-left text-sm font-medium transition-all outline-none disabled:pointer-events-none disabled:opacity-50",
49
+ !isChevronLeft && "justify-between",
50
+ variantConfig?.trigger,
51
+ className
52
+ ),
53
+ ...props,
54
+ children: [
55
+ isChevronLeft && chevron,
56
+ children,
57
+ !isChevronLeft && chevron
58
+ ]
59
+ }
60
+ ) });
61
+ };
62
+ const AccordionContent = ({
63
+ className,
64
+ children,
65
+ ...props
66
+ }) => {
67
+ return /* @__PURE__ */ jsx(
68
+ AccordionPrimitive.Content,
69
+ {
70
+ "data-slot": "accordion-content",
71
+ className: "data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down overflow-hidden text-xs",
72
+ ...props,
73
+ children: /* @__PURE__ */ jsx("div", { className, children })
74
+ }
75
+ );
76
+ };
77
+ export {
78
+ Accordion,
79
+ AccordionContent,
80
+ AccordionItem,
81
+ AccordionTrigger
82
+ };
@@ -0,0 +1,41 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { cn } from "../../lib/cn.js";
3
+ import { AccordionContent, AccordionItem, AccordionTrigger } from "./Accordion.js";
4
+ const AccordionSection = ({
5
+ value,
6
+ title,
7
+ description,
8
+ children,
9
+ itemClassName,
10
+ triggerClassName,
11
+ contentClassName
12
+ }) => {
13
+ return /* @__PURE__ */ jsxs(
14
+ AccordionItem,
15
+ {
16
+ value,
17
+ className: cn(
18
+ "border-border bg-primary overflow-hidden rounded-sm border last:border-b-1",
19
+ itemClassName
20
+ ),
21
+ children: [
22
+ /* @__PURE__ */ jsx(
23
+ AccordionTrigger,
24
+ {
25
+ className: cn("hover:bg-secondary items-center justify-start gap-4 px-4 py-2", triggerClassName),
26
+ chevronPosition: "left",
27
+ chevronVariant: "section",
28
+ children: /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-2", children: [
29
+ typeof title === "string" ? /* @__PURE__ */ jsx("h6", { className: "text-default text-xs font-medium", children: title }) : title,
30
+ description != null && (typeof description === "string" ? /* @__PURE__ */ jsx("p", { className: "text-gray-chateau text-2xs", children: description }) : description)
31
+ ] })
32
+ }
33
+ ),
34
+ /* @__PURE__ */ jsx(AccordionContent, { className: cn("border-border bg-secondary border-t", contentClassName), children })
35
+ ]
36
+ }
37
+ );
38
+ };
39
+ export {
40
+ AccordionSection
41
+ };
@@ -0,0 +1,29 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { cn } from "../../lib/cn.js";
3
+ import { AccordionTrigger } from "./Accordion.js";
4
+ const FolderTreeExpandTrigger = ({
5
+ label,
6
+ className,
7
+ chevronVariant = "tree",
8
+ ...props
9
+ }) => {
10
+ return /* @__PURE__ */ jsx(
11
+ AccordionTrigger,
12
+ {
13
+ className: cn(
14
+ "text-subdued shrink-0 rounded-xs p-0 text-xs font-normal hover:cursor-pointer hover:no-underline",
15
+ className
16
+ ),
17
+ chevronPosition: "left",
18
+ chevronVariant,
19
+ ...props,
20
+ children: /* @__PURE__ */ jsxs("span", { className: "sr-only", children: [
21
+ "Expand ",
22
+ label
23
+ ] })
24
+ }
25
+ );
26
+ };
27
+ export {
28
+ FolderTreeExpandTrigger
29
+ };
@@ -0,0 +1,31 @@
1
+ const accordionChevronVariants = {
2
+ down: {
3
+ trigger: "[&[data-state=open]>svg]:rotate-180",
4
+ icon: ""
5
+ },
6
+ section: {
7
+ trigger: "",
8
+ icon: "rotate-[-90deg] group-data-[state=open]/accordion-trigger:rotate-0"
9
+ },
10
+ tree: {
11
+ trigger: "",
12
+ icon: "size-3 translate-y-0 rotate-[-90deg] group-data-[state=open]/accordion-trigger:rotate-0"
13
+ },
14
+ "tree-sm": {
15
+ trigger: "",
16
+ icon: "mb-1 size-3.5 rotate-[-90deg] group-data-[state=open]/accordion-trigger:rotate-0"
17
+ }
18
+ };
19
+ function resolveAccordionChevronVariant(chevronPosition, chevronVariant) {
20
+ if (chevronVariant) {
21
+ return chevronVariant;
22
+ }
23
+ if (chevronPosition) {
24
+ return "down";
25
+ }
26
+ return "none";
27
+ }
28
+ export {
29
+ accordionChevronVariants,
30
+ resolveAccordionChevronVariant
31
+ };