@skiddph/prui 0.1.0

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 (69) hide show
  1. package/LICENSE +201 -0
  2. package/dist/app/app.d.ts +91 -0
  3. package/dist/app/auto-pages.d.ts +20 -0
  4. package/dist/app/form.d.ts +44 -0
  5. package/dist/app/index.d.ts +8 -0
  6. package/dist/app/resource.d.ts +61 -0
  7. package/dist/app/settings.d.ts +27 -0
  8. package/dist/app/stat-row.d.ts +20 -0
  9. package/dist/app.js +18 -0
  10. package/dist/chunks/data-table-toolbar-C9likJBN.js +430 -0
  11. package/dist/chunks/settings-DUz5nyX-.js +731 -0
  12. package/dist/core/button.d.ts +14 -0
  13. package/dist/core/button.js +58 -0
  14. package/dist/core/card.d.ts +24 -0
  15. package/dist/core/card.js +122 -0
  16. package/dist/core/cn.d.ts +3 -0
  17. package/dist/core/cn.js +8 -0
  18. package/dist/core/dialog.d.ts +25 -0
  19. package/dist/core/dialog.js +102 -0
  20. package/dist/core/dropdown.d.ts +24 -0
  21. package/dist/core/dropdown.js +89 -0
  22. package/dist/core/index.d.ts +14 -0
  23. package/dist/core/input.d.ts +8 -0
  24. package/dist/core/input.js +42 -0
  25. package/dist/core/label.d.ts +12 -0
  26. package/dist/core/label.js +52 -0
  27. package/dist/core/modal.d.ts +56 -0
  28. package/dist/core/modal.js +303 -0
  29. package/dist/core/props-meta.d.ts +26 -0
  30. package/dist/core/props-meta.js +1 -0
  31. package/dist/core/scroll-area.d.ts +8 -0
  32. package/dist/core/scroll-area.js +27 -0
  33. package/dist/core/select.d.ts +38 -0
  34. package/dist/core/select.js +157 -0
  35. package/dist/core/switch.d.ts +10 -0
  36. package/dist/core/switch.js +57 -0
  37. package/dist/core/tabs.d.ts +22 -0
  38. package/dist/core/tabs.js +94 -0
  39. package/dist/core.js +64 -0
  40. package/dist/data-table/data-table-daterange-filter.d.ts +14 -0
  41. package/dist/data-table/data-table-faceted-filter.d.ts +17 -0
  42. package/dist/data-table/data-table-number-range-filter.d.ts +14 -0
  43. package/dist/data-table/data-table-pagination.d.ts +24 -0
  44. package/dist/data-table/data-table-toolbar.d.ts +38 -0
  45. package/dist/data-table/data-table.d.ts +47 -0
  46. package/dist/data-table/index.d.ts +7 -0
  47. package/dist/data-table.js +12 -0
  48. package/dist/index.d.ts +5 -0
  49. package/dist/index.js +125 -0
  50. package/dist/pages/forgot-password.d.ts +21 -0
  51. package/dist/pages/index.d.ts +18 -0
  52. package/dist/pages/login.d.ts +24 -0
  53. package/dist/pages/logout.d.ts +12 -0
  54. package/dist/pages/otp.d.ts +18 -0
  55. package/dist/pages/profile-settings.d.ts +55 -0
  56. package/dist/pages/register.d.ts +19 -0
  57. package/dist/pages/reset-password.d.ts +20 -0
  58. package/dist/pages/shared.d.ts +55 -0
  59. package/dist/pages/status.d.ts +33 -0
  60. package/dist/pages.js +806 -0
  61. package/dist/prui.css +120 -0
  62. package/dist/theme/base.css +36 -0
  63. package/dist/theme/control.css +16 -0
  64. package/dist/theme/daylight.css +16 -0
  65. package/dist/theme/ember.css +16 -0
  66. package/dist/theme/index.d.ts +55 -0
  67. package/dist/theme/workshop.css +16 -0
  68. package/dist/theme.js +63 -0
  69. package/package.json +81 -0
package/dist/prui.css ADDED
@@ -0,0 +1,120 @@
1
+ /*
2
+ PRUI base tokens. Every theme defines these CSS variables; components only
3
+ ever reference the variables, so a single override file re-skins everything.
4
+ 6px radius system, dark-first, no gradient text.
5
+ */
6
+ .prui-root,
7
+ :root {
8
+ --prui-radius-1: 3px;
9
+ --prui-radius-2: 6px;
10
+ --prui-radius-3: 10px;
11
+ --prui-radius-full: 9999px;
12
+ --prui-dim-op: 0.62;
13
+ }
14
+
15
+ /* control (dark, blue accent) is the default theme */
16
+ /* Theme: control. Direction D "Control Room" — pure black, periwinkle accent. Default theme. */
17
+ .prui-theme-control {
18
+ color-scheme: dark;
19
+ --prui-background: #000000;
20
+ --prui-surface: #0f0f10;
21
+ --prui-raise: #1a1a1c;
22
+ --prui-line: #2a2a2e;
23
+ --prui-fg: #f4f4f5;
24
+ --prui-dim: #9b9ba4;
25
+ --prui-brand: #7c9cff;
26
+ --prui-brand-fg: #0a0f24;
27
+ --prui-ok: #3ddc97;
28
+ --prui-warn: #ffc15e;
29
+ --prui-danger: #f87171;
30
+ --prui-radius: 6px;
31
+ }
32
+
33
+ /* Modal shake feedback (blocked close), from icanhelp modal */
34
+ @keyframes prui-modal-shake {
35
+ 0%, 100% { transform: scale(1) translateY(0) translateX(0); }
36
+ 10%, 30%, 50%, 70%, 90% { transform: scale(1) translateY(0) translateX(-8px); }
37
+ 20%, 40%, 60%, 80% { transform: scale(1) translateY(0) translateX(8px); }
38
+ }
39
+ .prui-modal-shake { animation: prui-modal-shake 0.5s ease-in-out; }
40
+ body.modal-open { overflow: hidden; }
41
+
42
+ /* p4 rail scrollbar: thin, surfaces matching */
43
+ .prui-app aside ::-webkit-scrollbar,
44
+ .prui-app aside::-webkit-scrollbar { width: 8px; }
45
+ .prui-app aside ::-webkit-scrollbar-track,
46
+ .prui-app aside::-webkit-scrollbar-track { background: transparent; }
47
+ .prui-app aside ::-webkit-scrollbar-thumb,
48
+ .prui-app aside::-webkit-scrollbar-thumb { background: var(--prui-raise); border-radius: 4px; }
49
+ .prui-app aside ::-webkit-scrollbar-thumb:hover,
50
+ .prui-app aside::-webkit-scrollbar-thumb:hover { background: var(--prui-line); }
51
+ .prui-app aside { scrollbar-width: thin; scrollbar-color: var(--prui-raise) transparent; }
52
+
53
+ /* Theme: control. Direction D "Control Room" — pure black, periwinkle accent. Default theme. */
54
+ .prui-theme-control {
55
+ color-scheme: dark;
56
+ --prui-background: #000000;
57
+ --prui-surface: #0f0f10;
58
+ --prui-raise: #1a1a1c;
59
+ --prui-line: #2a2a2e;
60
+ --prui-fg: #f4f4f5;
61
+ --prui-dim: #9b9ba4;
62
+ --prui-brand: #7c9cff;
63
+ --prui-brand-fg: #0a0f24;
64
+ --prui-ok: #3ddc97;
65
+ --prui-warn: #ffc15e;
66
+ --prui-danger: #f87171;
67
+ --prui-radius: 6px;
68
+ }
69
+
70
+ /* Theme: workshop. Dark warm neutral, amber accent. */
71
+ .prui-theme-workshop {
72
+ color-scheme: dark;
73
+ --prui-background: #14120e;
74
+ --prui-surface: #1c1915;
75
+ --prui-raise: #26221c;
76
+ --prui-line: #362f26;
77
+ --prui-fg: #f0e9dd;
78
+ --prui-dim: #a89c88;
79
+ --prui-brand: #d97706;
80
+ --prui-brand-fg: #ffffff;
81
+ --prui-ok: #4ade80;
82
+ --prui-warn: #fbbf24;
83
+ --prui-danger: #f87171;
84
+ --prui-radius: 6px;
85
+ }
86
+
87
+ /* Theme: ember. Deep dark red-black, ember accent. */
88
+ .prui-theme-ember {
89
+ color-scheme: dark;
90
+ --prui-background: #120c0c;
91
+ --prui-surface: #1a1112;
92
+ --prui-raise: #251719;
93
+ --prui-line: #3a2124;
94
+ --prui-fg: #f3e4e4;
95
+ --prui-dim: #b09090;
96
+ --prui-brand: #f05252;
97
+ --prui-brand-fg: #ffffff;
98
+ --prui-ok: #34d399;
99
+ --prui-warn: #fb923c;
100
+ --prui-danger: #ef4444;
101
+ --prui-radius: 6px;
102
+ }
103
+
104
+ /* Theme: daylight. Light theme, indigo accent. */
105
+ .prui-theme-daylight {
106
+ color-scheme: light;
107
+ --prui-background: #f7f8fa;
108
+ --prui-surface: #ffffff;
109
+ --prui-raise: #f1f3f6;
110
+ --prui-line: #e2e6ec;
111
+ --prui-fg: #171b21;
112
+ --prui-dim: #5c6673;
113
+ --prui-brand: #4f46e5;
114
+ --prui-brand-fg: #ffffff;
115
+ --prui-ok: #16a34a;
116
+ --prui-warn: #d97706;
117
+ --prui-danger: #dc2626;
118
+ --prui-radius: 6px;
119
+ }
120
+
@@ -0,0 +1,36 @@
1
+ /*
2
+ PRUI base tokens. Every theme defines these CSS variables; components only
3
+ ever reference the variables, so a single override file re-skins everything.
4
+ 6px radius system, dark-first, no gradient text.
5
+ */
6
+ .prui-root,
7
+ :root {
8
+ --prui-radius-1: 3px;
9
+ --prui-radius-2: 6px;
10
+ --prui-radius-3: 10px;
11
+ --prui-radius-full: 9999px;
12
+ --prui-dim-op: 0.62;
13
+ }
14
+
15
+ /* control (dark, blue accent) is the default theme */
16
+ @import "./control.css";
17
+
18
+ /* Modal shake feedback (blocked close), from icanhelp modal */
19
+ @keyframes prui-modal-shake {
20
+ 0%, 100% { transform: scale(1) translateY(0) translateX(0); }
21
+ 10%, 30%, 50%, 70%, 90% { transform: scale(1) translateY(0) translateX(-8px); }
22
+ 20%, 40%, 60%, 80% { transform: scale(1) translateY(0) translateX(8px); }
23
+ }
24
+ .prui-modal-shake { animation: prui-modal-shake 0.5s ease-in-out; }
25
+ body.modal-open { overflow: hidden; }
26
+
27
+ /* p4 rail scrollbar: thin, surfaces matching */
28
+ .prui-app aside ::-webkit-scrollbar,
29
+ .prui-app aside::-webkit-scrollbar { width: 8px; }
30
+ .prui-app aside ::-webkit-scrollbar-track,
31
+ .prui-app aside::-webkit-scrollbar-track { background: transparent; }
32
+ .prui-app aside ::-webkit-scrollbar-thumb,
33
+ .prui-app aside::-webkit-scrollbar-thumb { background: var(--prui-raise); border-radius: 4px; }
34
+ .prui-app aside ::-webkit-scrollbar-thumb:hover,
35
+ .prui-app aside::-webkit-scrollbar-thumb:hover { background: var(--prui-line); }
36
+ .prui-app aside { scrollbar-width: thin; scrollbar-color: var(--prui-raise) transparent; }
@@ -0,0 +1,16 @@
1
+ /* Theme: control. Direction D "Control Room" — pure black, periwinkle accent. Default theme. */
2
+ .prui-theme-control {
3
+ color-scheme: dark;
4
+ --prui-background: #000000;
5
+ --prui-surface: #0f0f10;
6
+ --prui-raise: #1a1a1c;
7
+ --prui-line: #2a2a2e;
8
+ --prui-fg: #f4f4f5;
9
+ --prui-dim: #9b9ba4;
10
+ --prui-brand: #7c9cff;
11
+ --prui-brand-fg: #0a0f24;
12
+ --prui-ok: #3ddc97;
13
+ --prui-warn: #ffc15e;
14
+ --prui-danger: #f87171;
15
+ --prui-radius: 6px;
16
+ }
@@ -0,0 +1,16 @@
1
+ /* Theme: daylight. Light theme, indigo accent. */
2
+ .prui-theme-daylight {
3
+ color-scheme: light;
4
+ --prui-background: #f7f8fa;
5
+ --prui-surface: #ffffff;
6
+ --prui-raise: #f1f3f6;
7
+ --prui-line: #e2e6ec;
8
+ --prui-fg: #171b21;
9
+ --prui-dim: #5c6673;
10
+ --prui-brand: #4f46e5;
11
+ --prui-brand-fg: #ffffff;
12
+ --prui-ok: #16a34a;
13
+ --prui-warn: #d97706;
14
+ --prui-danger: #dc2626;
15
+ --prui-radius: 6px;
16
+ }
@@ -0,0 +1,16 @@
1
+ /* Theme: ember. Deep dark red-black, ember accent. */
2
+ .prui-theme-ember {
3
+ color-scheme: dark;
4
+ --prui-background: #120c0c;
5
+ --prui-surface: #1a1112;
6
+ --prui-raise: #251719;
7
+ --prui-line: #3a2124;
8
+ --prui-fg: #f3e4e4;
9
+ --prui-dim: #b09090;
10
+ --prui-brand: #f05252;
11
+ --prui-brand-fg: #ffffff;
12
+ --prui-ok: #34d399;
13
+ --prui-warn: #fb923c;
14
+ --prui-danger: #ef4444;
15
+ --prui-radius: 6px;
16
+ }
@@ -0,0 +1,55 @@
1
+ /**
2
+ * PRUI theme system.
3
+ * Tokens are CSS variables set by the named theme classes in this package.
4
+ * applyTheme() sets the theme class plus data-mode on the target element.
5
+ */
6
+ export declare const PRUI_THEMES: readonly ["control", "workshop", "ember", "daylight"];
7
+ export type ThemeName = (typeof PRUI_THEMES)[number];
8
+ export type ThemeMode = "light" | "dark";
9
+ export declare function isDarkTheme(name: ThemeName): boolean;
10
+ export declare function isLightTheme(name: ThemeName): boolean;
11
+ export declare function themeMode(name: ThemeName): ThemeMode;
12
+ export interface ApplyThemeOptions {
13
+ /** Theme name, defaults to control. */
14
+ theme?: ThemeName;
15
+ /** Force a mode; omit to use the theme's natural mode. */
16
+ mode?: ThemeMode;
17
+ /** Element to class, defaults to document.documentElement. */
18
+ target?: HTMLElement | null;
19
+ /** Persistence key; set null to disable persistence. Defaults to prui:theme. */
20
+ storageKey?: string | null;
21
+ }
22
+ export interface AppliedTheme {
23
+ theme: ThemeName;
24
+ mode: ThemeMode;
25
+ }
26
+ export declare function applyTheme(options?: ApplyThemeOptions): AppliedTheme;
27
+ /** Read a persisted theme previously written by applyTheme. */
28
+ export declare function readPersistedTheme(storageKey?: string): AppliedTheme | null;
29
+ /** Cycle through dark themes and the light theme for a toggle button. */
30
+ export declare function nextTheme(current: ThemeName): ThemeName;
31
+ export declare const themeMeta: {
32
+ readonly name: "applyTheme";
33
+ readonly description: "Apply a named PRUI theme and persist the choice.";
34
+ readonly props: readonly [{
35
+ readonly name: "theme";
36
+ readonly type: "'control' | 'workshop' | 'ember' | 'daylight'";
37
+ readonly default: "'control'";
38
+ readonly control: "select";
39
+ }, {
40
+ readonly name: "mode";
41
+ readonly type: "'light' | 'dark'";
42
+ readonly default: "theme natural mode";
43
+ readonly control: "select";
44
+ }, {
45
+ readonly name: "target";
46
+ readonly type: "HTMLElement";
47
+ readonly default: "document.documentElement";
48
+ readonly control: "none";
49
+ }, {
50
+ readonly name: "storageKey";
51
+ readonly type: "string | null";
52
+ readonly default: "'prui:theme'";
53
+ readonly control: "text";
54
+ }];
55
+ };
@@ -0,0 +1,16 @@
1
+ /* Theme: workshop. Dark warm neutral, amber accent. */
2
+ .prui-theme-workshop {
3
+ color-scheme: dark;
4
+ --prui-background: #14120e;
5
+ --prui-surface: #1c1915;
6
+ --prui-raise: #26221c;
7
+ --prui-line: #362f26;
8
+ --prui-fg: #f0e9dd;
9
+ --prui-dim: #a89c88;
10
+ --prui-brand: #d97706;
11
+ --prui-brand-fg: #ffffff;
12
+ --prui-ok: #4ade80;
13
+ --prui-warn: #fbbf24;
14
+ --prui-danger: #f87171;
15
+ --prui-radius: 6px;
16
+ }
package/dist/theme.js ADDED
@@ -0,0 +1,63 @@
1
+ const l = ["control", "workshop", "ember", "daylight"], i = ["control", "workshop", "ember"], m = ["daylight"];
2
+ function d(e) {
3
+ return i.includes(e);
4
+ }
5
+ function p(e) {
6
+ return m.includes(e);
7
+ }
8
+ function c(e) {
9
+ return d(e) ? "dark" : "light";
10
+ }
11
+ const s = "prui-theme-";
12
+ function u(e, t) {
13
+ return [`${s}${e}`, "prui-root", `prui-mode-${t}`];
14
+ }
15
+ function h(e) {
16
+ const t = [...e.classList].filter(
17
+ (n) => n.startsWith(s) || n === "prui-root" || n.startsWith("prui-mode-")
18
+ );
19
+ t.length && e.classList.remove(...t);
20
+ }
21
+ function f(e = {}) {
22
+ const t = e.theme ?? "control", n = e.mode ?? c(t), o = e.target ?? (typeof document < "u" ? document.documentElement : null);
23
+ o && (h(o), o.classList.add(...u(t, n)), o.dataset.pruiTheme = t, o.dataset.pruiMode = n, o.style.colorScheme = n);
24
+ const r = e.storageKey === void 0 ? "prui:theme" : e.storageKey;
25
+ return r && typeof localStorage < "u" && localStorage.setItem(r, JSON.stringify({ theme: t, mode: n })), { theme: t, mode: n };
26
+ }
27
+ function g(e = "prui:theme") {
28
+ if (typeof localStorage > "u") return null;
29
+ const t = localStorage.getItem(e);
30
+ if (!t) return null;
31
+ try {
32
+ const n = JSON.parse(t), o = l.find((a) => a === n.theme);
33
+ if (!o) return null;
34
+ const r = n.mode === "light" || n.mode === "dark" ? n.mode : c(o);
35
+ return { theme: o, mode: r };
36
+ } catch {
37
+ return null;
38
+ }
39
+ }
40
+ function y(e) {
41
+ const t = l.indexOf(e);
42
+ return l[(t + 1) % l.length] ?? "control";
43
+ }
44
+ const T = {
45
+ name: "applyTheme",
46
+ description: "Apply a named PRUI theme and persist the choice.",
47
+ props: [
48
+ { name: "theme", type: "'control' | 'workshop' | 'ember' | 'daylight'", default: "'control'", control: "select" },
49
+ { name: "mode", type: "'light' | 'dark'", default: "theme natural mode", control: "select" },
50
+ { name: "target", type: "HTMLElement", default: "document.documentElement", control: "none" },
51
+ { name: "storageKey", type: "string | null", default: "'prui:theme'", control: "text" }
52
+ ]
53
+ };
54
+ export {
55
+ l as PRUI_THEMES,
56
+ f as applyTheme,
57
+ d as isDarkTheme,
58
+ p as isLightTheme,
59
+ y as nextTheme,
60
+ g as readPersistedTheme,
61
+ T as themeMeta,
62
+ c as themeMode
63
+ };
package/package.json ADDED
@@ -0,0 +1,81 @@
1
+ {
2
+ "name": "@skiddph/prui",
3
+ "version": "0.1.0",
4
+ "description": "PRUI component system: primitives, app-layer super-components, pages, and themes",
5
+ "type": "module",
6
+ "license": "Apache-2.0",
7
+ "sideEffects": [
8
+ "**/*.css"
9
+ ],
10
+ "files": [
11
+ "dist"
12
+ ],
13
+ "exports": {
14
+ ".": {
15
+ "types": "./dist/index.d.ts",
16
+ "import": "./dist/index.js"
17
+ },
18
+ "./core": {
19
+ "types": "./dist/core/index.d.ts",
20
+ "import": "./dist/core.js"
21
+ },
22
+ "./core/*": {
23
+ "types": "./dist/core/*.d.ts",
24
+ "import": "./dist/core/*.js"
25
+ },
26
+ "./app": {
27
+ "types": "./dist/app/index.d.ts",
28
+ "import": "./dist/app.js"
29
+ },
30
+ "./pages": {
31
+ "types": "./dist/pages/index.d.ts",
32
+ "import": "./dist/pages.js"
33
+ },
34
+ "./data-table": {
35
+ "types": "./dist/data-table/index.d.ts",
36
+ "import": "./dist/data-table.js"
37
+ },
38
+ "./theme": {
39
+ "types": "./dist/theme/index.d.ts",
40
+ "import": "./dist/theme.js"
41
+ },
42
+ "./theme/*.css": "./dist/theme/*.css",
43
+ "./styles.css": "./dist/prui.css"
44
+ },
45
+ "dependencies": {
46
+ "clsx": "^2.1.1",
47
+ "lucide-react": "^0.525.0",
48
+ "react": "^19.1.0",
49
+ "react-dom": "^19.1.0",
50
+ "react-router-dom": "^7.6.0",
51
+ "tailwind-merge": "^3.3.1"
52
+ },
53
+ "devDependencies": {
54
+ "@testing-library/jest-dom": "^6.6.3",
55
+ "@testing-library/react": "^16.3.0",
56
+ "@testing-library/user-event": "^14.6.1",
57
+ "@types/node": "^22.20.2",
58
+ "@types/react": "^19.1.0",
59
+ "@types/react-dom": "^19.1.0",
60
+ "@vitejs/plugin-react": "^4.5.0",
61
+ "jsdom": "^26.1.0",
62
+ "typescript": "^5.9.3",
63
+ "vite": "^6.3.5",
64
+ "vite-plugin-dts": "^4.5.4",
65
+ "vitest": "^3.2.4"
66
+ },
67
+ "repository": {
68
+ "type": "git",
69
+ "url": "git+https://github.com/eru123/prui.git"
70
+ },
71
+ "publishConfig": {
72
+ "registry": "https://registry.npmjs.org/",
73
+ "access": "public"
74
+ },
75
+ "scripts": {
76
+ "build": "vite build && node scripts/bundle-css.mjs && mkdir -p dist/theme && cp src/theme/*.css dist/theme/",
77
+ "test": "vitest run",
78
+ "typecheck": "tsc --noEmit",
79
+ "clean": "rm -rf dist"
80
+ }
81
+ }