@robert-stackflow/oneui 0.1.0 → 0.3.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 (94) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/README.md +58 -2
  3. package/components/AppShell.d.ts +11 -4
  4. package/components/AppShell.js +79 -54
  5. package/components/AppShell.module.css +16 -4
  6. package/components/AppearanceSettings.js +1 -1
  7. package/components/Button.d.ts +9 -2
  8. package/components/Button.js +30 -7
  9. package/components/Button.module.css +16 -7
  10. package/components/Calendar.d.ts +2 -1
  11. package/components/Calendar.js +4 -3
  12. package/components/Card.d.ts +2 -1
  13. package/components/Card.js +13 -3
  14. package/components/Card.module.css +19 -0
  15. package/components/Checkbox.module.css +3 -3
  16. package/components/Combobox.d.ts +4 -2
  17. package/components/Combobox.js +162 -76
  18. package/components/Combobox.module.css +5 -7
  19. package/components/Control.module.css +18 -5
  20. package/components/DatePicker.d.ts +3 -0
  21. package/components/DatePicker.js +41 -21
  22. package/components/DatePicker.module.css +3 -0
  23. package/components/Dialog.d.ts +6 -1
  24. package/components/Dialog.js +19 -6
  25. package/components/Dialog.module.css +17 -0
  26. package/components/DialogVariants.d.ts +27 -0
  27. package/components/DialogVariants.js +161 -0
  28. package/components/DialogVariants.module.css +29 -0
  29. package/components/HierarchyPicker.module.css +35 -0
  30. package/components/IconButton.module.css +5 -2
  31. package/components/IconPicker.d.ts +14 -4
  32. package/components/IconPicker.js +67 -25
  33. package/components/Indicator.module.css +1 -1
  34. package/components/Input.d.ts +2 -1
  35. package/components/Input.js +12 -4
  36. package/components/Input.module.css +18 -1
  37. package/components/LoadingState.d.ts +3 -1
  38. package/components/LoadingState.js +26 -15
  39. package/components/LoadingState.module.css +3 -0
  40. package/components/MenuItem.d.ts +2 -1
  41. package/components/MenuItem.js +2 -0
  42. package/components/MenuItem.module.css +9 -0
  43. package/components/MultiSelect.d.ts +2 -1
  44. package/components/MultiSelect.js +66 -2
  45. package/components/MultiSelect.module.css +38 -0
  46. package/components/NumberInput.js +1 -0
  47. package/components/OptionList.module.css +12 -0
  48. package/components/PasswordField.js +1 -0
  49. package/components/PinInput.js +1 -0
  50. package/components/Popover.d.ts +4 -1
  51. package/components/Popover.js +11 -5
  52. package/components/Popover.module.css +3 -0
  53. package/components/RadioGroup.module.css +2 -2
  54. package/components/SearchField.js +1 -0
  55. package/components/Select.js +1 -0
  56. package/components/Select.module.css +3 -0
  57. package/components/SelectionTag.d.ts +8 -0
  58. package/components/SelectionTag.js +39 -0
  59. package/components/SettingsLayout.d.ts +3 -1
  60. package/components/SettingsLayout.js +19 -3
  61. package/components/SettingsLayout.module.css +20 -0
  62. package/components/Switch.module.css +8 -5
  63. package/components/Table.d.ts +6 -2
  64. package/components/Table.js +14 -4
  65. package/components/TagInput.js +11 -23
  66. package/components/TagInput.module.css +1 -1
  67. package/components/ThemeProvider.js +17 -3
  68. package/components/ToastProvider.d.ts +4 -4
  69. package/components/ToastProvider.js +19 -22
  70. package/components/TreeGuides.d.ts +9 -0
  71. package/components/TreeGuides.js +39 -0
  72. package/components/TreeGuides.module.css +45 -0
  73. package/components/TreeSelect.d.ts +3 -0
  74. package/components/TreeSelect.js +49 -21
  75. package/components/TreeTable.d.ts +15 -0
  76. package/components/TreeTable.js +151 -0
  77. package/components/TreeTable.module.css +53 -0
  78. package/components/VirtualPickerList.d.ts +2 -0
  79. package/components/VirtualPickerList.js +1 -1
  80. package/components/VirtualPickerList.module.css +4 -0
  81. package/components/appearance.d.ts +1 -0
  82. package/components/appearance.js +15 -6
  83. package/components/calendarNow.d.ts +5 -0
  84. package/components/calendarNow.js +27 -0
  85. package/components/createToaster.d.ts +12 -0
  86. package/components/createToaster.js +40 -0
  87. package/components/hierarchy.d.ts +1 -0
  88. package/components/index.d.ts +6 -3
  89. package/components/index.js +13 -1
  90. package/components/usePopover.d.ts +2 -2
  91. package/package.json +36 -4
  92. package/styles/base.css +20 -3
  93. package/styles/blue.css +49 -35
  94. package/styles/minimal.css +2 -1
@@ -0,0 +1,12 @@
1
+ import type { ToastMessage, ToastOptions, ToastTone } from "./ToastProvider";
2
+ export type ToastNotify = (message: string, options?: ToastOptions | ToastTone) => () => void;
3
+ export interface ToastController {
4
+ readonly id: string;
5
+ notify: ToastNotify;
6
+ dismiss(id?: number): void;
7
+ clear(id?: number): void;
8
+ subscribe(listener: () => void): () => void;
9
+ getSnapshot(): ToastMessage | null;
10
+ }
11
+ /** An isolated notification service; no React or document access is required. */
12
+ export declare function createToaster(): ToastController;
@@ -0,0 +1,40 @@
1
+ let nextController = 0;
2
+ function createToaster() {
3
+ let current = null, counter = 0;
4
+ const listeners = /* @__PURE__ */ new Set();
5
+ const publish = (message) => {
6
+ if (current === message) return;
7
+ current = message;
8
+ listeners.forEach((listener) => listener());
9
+ };
10
+ const dismiss = (id = current?.id) => {
11
+ if (current && current.id === id && !current.closing)
12
+ publish({ ...current, closing: true });
13
+ };
14
+ return {
15
+ id: "oneui-toast-" + ++nextController,
16
+ notify(message, options) {
17
+ const id = ++counter;
18
+ publish({
19
+ message,
20
+ id,
21
+ options: typeof options === "string" ? { tone: options } : options
22
+ });
23
+ return () => dismiss(id);
24
+ },
25
+ dismiss,
26
+ clear(id = current?.id) {
27
+ if (current?.id === id) publish(null);
28
+ },
29
+ subscribe(listener) {
30
+ listeners.add(listener);
31
+ return () => {
32
+ listeners.delete(listener);
33
+ };
34
+ },
35
+ getSnapshot: () => current
36
+ };
37
+ }
38
+ export {
39
+ createToaster
40
+ };
@@ -3,6 +3,7 @@ export type HierarchyOption = {
3
3
  value: string;
4
4
  label: string;
5
5
  icon?: ReactNode;
6
+ count?: number;
6
7
  keywords?: string[];
7
8
  children?: HierarchyOption[];
8
9
  disabled?: boolean;
@@ -47,7 +47,7 @@ export { CharacterPicker } from "./CharacterPicker";
47
47
  export { DataTable } from "./DataTable";
48
48
  export { EmojiPicker } from "./EmojiPicker";
49
49
  export { FileTree } from "./FileTree";
50
- export { IconPicker } from "./IconPicker";
50
+ export { IconPicker, type IconPickerProps, type IconPickerOption, } from "./IconPicker";
51
51
  export { LoadingOverlay } from "./LoadingOverlay";
52
52
  export { LoadingState } from "./LoadingState";
53
53
  export { Pagination } from "./Pagination";
@@ -84,7 +84,7 @@ export type { FormController, FormRules, FieldRule } from "./useFormState";
84
84
  export { PinInput } from "./PinInput";
85
85
  export { ContributionCalendar } from "./ContributionCalendar";
86
86
  export type { ContributionDay } from "./contribution";
87
- export { Combobox } from "./Combobox";
87
+ export { Combobox, type ComboboxProps } from "./Combobox";
88
88
  export { TagInput } from "./TagInput";
89
89
  export { PasswordField } from "./PasswordField";
90
90
  export { Alert } from "./Alert";
@@ -143,8 +143,11 @@ export { ThemeProvider } from "./ThemeProvider";
143
143
  export type { UITheme, ColorMode } from "./ThemeProvider";
144
144
  export { ThemeStylePicker } from "./ThemeStylePicker";
145
145
  export { AppShell, ShellHeader } from "./AppShell";
146
- export type { NavigationItem } from "./AppShell";
146
+ export type { NavigationItem, AppShellProps } from "./AppShell";
147
147
  export { SettingsLayout, SettingsCard } from "./SettingsLayout";
148
148
  export { AppearanceSettings } from "./AppearanceSettings";
149
149
  export { appearanceDefaults, normalizeAppearance } from "./appearance";
150
150
  export type { AppearancePreferences } from "./appearance";
151
+ export { MessageDialog, ConfirmDialog, FormDialog } from "./DialogVariants";
152
+ export { TreeTable, type TreeTableProps } from "./TreeTable";
153
+ export { createToaster, type ToastController, type ToastNotify, } from "./createToaster";
@@ -43,7 +43,9 @@ import { CharacterPicker } from "./CharacterPicker.js";
43
43
  import { DataTable } from "./DataTable.js";
44
44
  import { EmojiPicker } from "./EmojiPicker.js";
45
45
  import { FileTree } from "./FileTree.js";
46
- import { IconPicker } from "./IconPicker.js";
46
+ import {
47
+ IconPicker
48
+ } from "./IconPicker.js";
47
49
  import { LoadingOverlay } from "./LoadingOverlay.js";
48
50
  import { LoadingState } from "./LoadingState.js";
49
51
  import { Pagination } from "./Pagination.js";
@@ -104,6 +106,11 @@ import { AppShell, ShellHeader } from "./AppShell.js";
104
106
  import { SettingsLayout, SettingsCard } from "./SettingsLayout.js";
105
107
  import { AppearanceSettings } from "./AppearanceSettings.js";
106
108
  import { appearanceDefaults, normalizeAppearance } from "./appearance.js";
109
+ import { MessageDialog, ConfirmDialog, FormDialog } from "./DialogVariants.js";
110
+ import { TreeTable } from "./TreeTable.js";
111
+ import {
112
+ createToaster
113
+ } from "./createToaster.js";
107
114
  export {
108
115
  Accordion,
109
116
  Alert,
@@ -125,6 +132,7 @@ export {
125
132
  ColorPicker,
126
133
  Combobox,
127
134
  CommandPalette,
135
+ ConfirmDialog,
128
136
  ContextMenu,
129
137
  ContextMenuPanel,
130
138
  ContributionCalendar,
@@ -144,6 +152,7 @@ export {
144
152
  FilePicker,
145
153
  FileTree,
146
154
  Form,
155
+ FormDialog,
147
156
  FormErrorSummary,
148
157
  FormField,
149
158
  FormGroup,
@@ -155,6 +164,7 @@ export {
155
164
  LoadingState,
156
165
  Menu,
157
166
  MenuItem,
167
+ MessageDialog,
158
168
  MultiSelect,
159
169
  NumberInput,
160
170
  Page,
@@ -204,12 +214,14 @@ export {
204
214
  ToastProvider,
205
215
  Tooltip,
206
216
  TreeSelect,
217
+ TreeTable,
207
218
  UIProvider,
208
219
  UnderlinedTab,
209
220
  Upload,
210
221
  UploadList,
211
222
  VirtualPickerList,
212
223
  appearanceDefaults,
224
+ createToaster,
213
225
  formatFileSize,
214
226
  normalizeAppearance,
215
227
  useFormState,
@@ -1,5 +1,5 @@
1
- export declare function usePopover(blocked?: boolean): {
2
- anchor: import("react").RefObject<HTMLButtonElement | null>;
1
+ export declare function usePopover<T extends HTMLElement = HTMLButtonElement>(blocked?: boolean): {
2
+ anchor: import("react").RefObject<T | null>;
3
3
  open: boolean;
4
4
  close: () => void;
5
5
  closeAndFocus: () => void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@robert-stackflow/oneui",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "description": "OneUI React components, application shell and portable visual themes",
5
5
  "type": "module",
6
6
  "sideEffects": [
@@ -763,17 +763,49 @@
763
763
  "types": "./components/appearance.d.ts",
764
764
  "import": "./components/appearance.js",
765
765
  "default": "./components/appearance.js"
766
+ },
767
+ "./DialogVariants": {
768
+ "types": "./components/DialogVariants.d.ts",
769
+ "import": "./components/DialogVariants.js",
770
+ "default": "./components/DialogVariants.js"
771
+ },
772
+ "./MessageDialog": {
773
+ "types": "./components/DialogVariants.d.ts",
774
+ "import": "./components/DialogVariants.js",
775
+ "default": "./components/DialogVariants.js"
776
+ },
777
+ "./ConfirmDialog": {
778
+ "types": "./components/DialogVariants.d.ts",
779
+ "import": "./components/DialogVariants.js",
780
+ "default": "./components/DialogVariants.js"
781
+ },
782
+ "./FormDialog": {
783
+ "types": "./components/DialogVariants.d.ts",
784
+ "import": "./components/DialogVariants.js",
785
+ "default": "./components/DialogVariants.js"
786
+ },
787
+ "./TreeTable": {
788
+ "types": "./components/TreeTable.d.ts",
789
+ "import": "./components/TreeTable.js",
790
+ "default": "./components/TreeTable.js"
791
+ },
792
+ "./TreeTable.module.css": "./components/TreeTable.module.css",
793
+ "./createToaster": {
794
+ "types": "./components/createToaster.d.ts",
795
+ "import": "./components/createToaster.js",
796
+ "default": "./components/createToaster.js"
766
797
  }
767
798
  },
768
799
  "files": [
769
800
  "components",
770
801
  "styles",
771
802
  "assets",
772
- "README.md"
803
+ "README.md",
804
+ "CHANGELOG.md"
773
805
  ],
774
806
  "peerDependencies": {
775
- "react": "19.3.1",
776
- "react-dom": "19.3.1"
807
+ "react": "^19.2.0",
808
+ "react-dom": "^19.2.0"
777
809
  },
778
810
  "dependencies": {
779
811
  "lucide-react": "1.59.0"
package/styles/base.css CHANGED
@@ -143,7 +143,11 @@
143
143
 
144
144
  :where(:root[data-ui-theme] *) {
145
145
  scrollbar-width: thin;
146
- scrollbar-color: color-mix(in srgb, var(--muted) 35%, transparent) transparent;
146
+ scrollbar-color: var(
147
+ --scrollbar-thumb,
148
+ color-mix(in srgb, var(--muted) 35%, transparent)
149
+ )
150
+ transparent;
147
151
  }
148
152
 
149
153
  @supports selector(::-webkit-scrollbar) {
@@ -169,14 +173,20 @@
169
173
  )::-webkit-scrollbar-thumb {
170
174
  border: 2px solid transparent;
171
175
  border-radius: 999px;
172
- background: color-mix(in srgb, var(--muted) 42%, transparent);
176
+ background: var(
177
+ --scrollbar-thumb,
178
+ color-mix(in srgb, var(--muted) 42%, transparent)
179
+ );
173
180
  background-clip: padding-box;
174
181
  }
175
182
  :where(
176
183
  :root[data-ui-theme],
177
184
  :root[data-ui-theme] *
178
185
  )::-webkit-scrollbar-thumb:hover {
179
- background-color: color-mix(in srgb, var(--muted) 65%, transparent);
186
+ background-color: var(
187
+ --scrollbar-hover,
188
+ color-mix(in srgb, var(--muted) 65%, transparent)
189
+ );
180
190
  }
181
191
  :where(
182
192
  :root[data-ui-theme],
@@ -187,3 +197,10 @@
187
197
  height: 0;
188
198
  }
189
199
  }
200
+
201
+ :root[data-ui-theme] {
202
+ --on-danger: #fff;
203
+ }
204
+ :root[data-ui-theme][data-theme="dark"] {
205
+ --on-danger: #141414;
206
+ }
package/styles/blue.css CHANGED
@@ -1,19 +1,28 @@
1
1
  :root[data-ui-theme="blue"] {
2
2
  color-scheme: light;
3
- --canvas: #f6f7fa;
3
+ --canvas: #f5f7fb;
4
4
  --surface: #fff;
5
5
  --elevated: #fff;
6
- --sidebar: #fbfcfe;
7
- --input: #fff;
8
- --hover: #f1f3f8;
9
- --text: #263149;
10
- --muted: #66748b;
11
- --placeholder: #707d91;
12
- --border: #e5e9f1;
13
- --border-strong: #cdd5e3;
14
- --accent: #5269b6;
15
- --accent-hover: #43599f;
16
- --accent-soft: #edf1fc;
6
+ --sidebar: var(--surface);
7
+ --input: #f9fafc;
8
+ --hover: #edf1f8;
9
+ --text: #25324a;
10
+ --muted: #8592a8;
11
+ --placeholder: color-mix(in srgb, var(--muted) 85%, transparent);
12
+ --border: #e3e8f1;
13
+ --border-strong: var(--border);
14
+ --accent: #5067b8;
15
+ --accent-hover: #4059aa;
16
+ --accent-soft: #ebeffb;
17
+ --accent-fill: #4059aa;
18
+ --accent-fill-hover: #354b91;
19
+ --on-accent-fill: #fff;
20
+ --switch-on: #526edb;
21
+ --switch-on-hover: #526edb;
22
+ --switch-thumb-on: #fff;
23
+ --navigation-active-color: var(--accent);
24
+ --scrollbar-thumb: #c1cada;
25
+ --scrollbar-hover: #97a7be;
17
26
  --on-accent: #fff;
18
27
  --success: #348769;
19
28
  --success-soft: #edf7f1;
@@ -25,28 +34,31 @@
25
34
  --radius-lg: 14px;
26
35
  --control-height: 40px;
27
36
  --space: 24px;
28
- --shadow: 0 3px 16px #273d6010;
29
- --shadow-lg: 0 16px 50px #17243e1c;
37
+ --shadow: 0 12px 36px rgb(29 44 75 / 4.5%);
38
+ --shadow-lg: 0 12px 40px #17244315, 0 2px 8px #17244308;
30
39
  --ease: cubic-bezier(0.2, 0.7, 0.2, 1);
31
40
  --fast: 160ms var(--ease);
32
41
  --sidebar-width: 228px;
33
42
  }
34
43
  :root[data-ui-theme="blue"][data-theme="dark"] {
35
44
  color-scheme: dark;
36
- --canvas: #10151e;
37
- --surface: #19212e;
38
- --elevated: #202a39;
39
- --sidebar: #141c28;
40
- --input: #151e2a;
41
- --hover: #243044;
42
- --text: #e0e7f2;
43
- --muted: #98a6bb;
44
- --placeholder: #6f7f96;
45
- --border: #2c384a;
46
- --border-strong: #41516a;
47
- --accent: #a7b9f1;
48
- --accent-hover: #c0cdf5;
49
- --accent-soft: #283650;
45
+ --canvas: #10151f;
46
+ --surface: #19212f;
47
+ --elevated: #202a3b;
48
+ --sidebar: var(--surface);
49
+ --input: #131c29;
50
+ --hover: #253147;
51
+ --text: #e1e8f4;
52
+ --muted: #95a4bd;
53
+ --border: #2c384d;
54
+ --border-strong: var(--border);
55
+ --accent: #afc1ff;
56
+ --accent-hover: #bdcbee;
57
+ --accent-soft: #263451;
58
+ --accent-fill: #2c3f78;
59
+ --accent-fill-hover: #25355f;
60
+ --scrollbar-thumb: #43516a;
61
+ --scrollbar-hover: #657794;
50
62
  --on-accent: #192540;
51
63
  --success: #87c7a8;
52
64
  --success-soft: #1d362e;
@@ -54,8 +66,8 @@
54
66
  --warning-soft: #383021;
55
67
  --danger: #ee9ba6;
56
68
  --danger-soft: #3e2632;
57
- --shadow: 0 3px 16px #00000012;
58
- --shadow-lg: 0 16px 50px #0005;
69
+ --shadow: 0 8px 30px #03081214;
70
+ --shadow-lg: 0 14px 44px #050a1455, 0 2px 8px #050a1430;
59
71
  }
60
72
  :root[data-ui-theme="blue"][data-accent="neutral"] {
61
73
  --accent: #343a46;
@@ -108,7 +120,7 @@
108
120
  --selected: var(--accent-soft);
109
121
  --navigation: var(--sidebar);
110
122
  --disabled: var(--placeholder);
111
- --control-border: var(--border-strong);
123
+ --control-border: var(--border);
112
124
  --separator-width: 1px;
113
125
  --separator-style: solid;
114
126
  --separator-color: var(--border);
@@ -119,7 +131,7 @@
119
131
  --menu-item-line-height: 20px;
120
132
  --menu-item-padding-x: 11px;
121
133
  --menu-item-gap: 10px;
122
- --menu-item-spacing: 2px;
134
+ --menu-item-spacing: 1px;
123
135
  --menu-item-icon-size: 16px;
124
136
  --menu-item-font-size: 13px;
125
137
  --menu-shortcut-font-size: 11px;
@@ -152,7 +164,7 @@
152
164
  --shadow-edge: #0004;
153
165
  --shadow-modal: #0008;
154
166
  --overlay: #050a1466;
155
- --control-border: #3b4a60;
167
+ --control-border: var(--border);
156
168
  }
157
169
  :root[data-ui-theme="blue"][data-density="compact"] {
158
170
  --control-small: 28px;
@@ -186,10 +198,12 @@
186
198
  --field-radius: var(--radius);
187
199
  --field-font-size: 13px;
188
200
  --field-line-height: 1.4;
201
+ /* Keep the previous token valid for consumers with older composed styles. */
189
202
  --field-hover-strength: 38%;
203
+ --field-hover-border: color-mix(in srgb, var(--accent) 35%, var(--border));
190
204
  --field-focus-border: var(--accent);
191
205
  --field-focus-width: 3px;
192
- --field-focus-strength: 14%;
206
+ --field-focus-strength: 12%;
193
207
  --field-disabled-opacity: 0.55;
194
208
  --field-readonly: var(--canvas);
195
209
  --field-gap: 8px;
@@ -198,7 +212,7 @@
198
212
  --field-message-size: 12px;
199
213
  --select-width: 168px;
200
214
  --popup-background: var(--elevated);
201
- --popup-border: var(--border-strong);
215
+ --popup-border: var(--border);
202
216
  --popup-radius: calc(var(--radius) + 2px);
203
217
  --popup-shadow: var(--shadow-lg);
204
218
  --dialog-width: 520px;
@@ -25,7 +25,7 @@
25
25
  --menu-item-line-height: 20px;
26
26
  --menu-item-padding-x: 10px;
27
27
  --menu-item-gap: 9px;
28
- --menu-item-spacing: 2px;
28
+ --menu-item-spacing: 1px;
29
29
  --menu-item-icon-size: 16px;
30
30
  --menu-item-font-size: 12px;
31
31
  --menu-shortcut-font-size: 11px;
@@ -68,6 +68,7 @@
68
68
  --hover: #303030;
69
69
  --selected: #3a3a3a;
70
70
  --navigation: #181819;
71
+ --navigation-selected-color: var(--fg);
71
72
  --canvas: #202021;
72
73
  --field: #252526;
73
74
  --disabled: #686868;