@dreamtree-org/twreact-ui 1.3.3 → 1.3.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.
- package/README.md +13 -6
- package/ai-skills/dreamtree-ui.md +5 -1
- package/dist/ai-schema.json +46 -3
- package/dist/components/core/Button.d.ts.map +1 -1
- package/dist/components/core/Radio.d.ts.map +1 -1
- package/dist/components/core/Select.d.ts.map +1 -1
- package/dist/components/core/Table/MobileCard.d.ts.map +1 -1
- package/dist/components/core/Table/TableRow.d.ts.map +1 -1
- package/dist/components/core/Table/helpers.d.ts +12 -0
- package/dist/components/core/Table/helpers.d.ts.map +1 -1
- package/dist/components/feedback/Dialog.d.ts.map +1 -1
- package/dist/components/feedback/Drawer.d.ts.map +1 -1
- package/dist/components/navigation/FootNav.d.ts.map +1 -1
- package/dist/components/utility/Badge.d.ts.map +1 -1
- package/dist/components/utility/Stepper.d.ts.map +1 -1
- package/dist/esm/components/blocks/StatusPill.js +1 -1
- package/dist/esm/components/core/Button.js +23 -6
- package/dist/esm/components/core/Radio.js +3 -2
- package/dist/esm/components/core/Select.js +12 -2
- package/dist/esm/components/core/Table/ActionMenu.js +5 -5
- package/dist/esm/components/core/Table/ColumnMenu.js +1 -1
- package/dist/esm/components/core/Table/FieldInput.js +5 -5
- package/dist/esm/components/core/Table/MobileCard.js +9 -10
- package/dist/esm/components/core/Table/MobileFilters.js +1 -1
- package/dist/esm/components/core/Table/Pagination.js +1 -1
- package/dist/esm/components/core/Table/Table.js +12 -12
- package/dist/esm/components/core/Table/TableRow.js +10 -11
- package/dist/esm/components/core/Table/helpers.js +16 -1
- package/dist/esm/components/feedback/Dialog.js +4 -2
- package/dist/esm/components/feedback/Drawer.js +39 -10
- package/dist/esm/components/navigation/Dropdown.js +1 -1
- package/dist/esm/components/navigation/FootNav.js +41 -14
- package/dist/esm/components/navigation/Navbar.js +21 -21
- package/dist/esm/components/navigation/Sidebar.js +12 -12
- package/dist/esm/components/utility/Badge.js +1 -0
- package/dist/esm/components/utility/Card.js +5 -5
- package/dist/esm/components/utility/Stepper.js +5 -2
- package/dist/esm/hooks/useSwipeToClose.js +66 -0
- package/dist/esm/utils/touchTarget.js +6 -0
- package/dist/hooks/useSwipeToClose.d.ts +24 -0
- package/dist/hooks/useSwipeToClose.d.ts.map +1 -0
- package/dist/index.css +1 -1
- package/dist/index.esm.css +1 -1
- package/dist/index.esm.js +287 -121
- package/dist/index.js +287 -121
- package/dist/types/index.d.ts +29 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/touchTarget.d.ts +2 -0
- package/dist/utils/touchTarget.d.ts.map +1 -0
- package/doc/README.md +1 -1
- package/mcp/README.md +1 -1
- package/mcp/catalog.snapshot.json +60 -30
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -214,12 +214,16 @@ Versatile button component with multiple variants and states.
|
|
|
214
214
|
- `leftIcon`: ReactNode
|
|
215
215
|
- `rightIcon`: ReactNode
|
|
216
216
|
- `fullWidth`: boolean
|
|
217
|
+
- `as`: ElementType — render as a link or router `Link` with the Button's look (a bare `href` renders an `<a>`)
|
|
218
|
+
- `href`: string
|
|
217
219
|
- `className`: string
|
|
218
220
|
|
|
219
221
|
```jsx
|
|
220
222
|
<Button variant="primary" size="lg" loading>
|
|
221
223
|
Loading...
|
|
222
224
|
</Button>
|
|
225
|
+
<Button href="tel:+919800000000" variant="outline">Call</Button>
|
|
226
|
+
<Button as={Link} to="/move-in">Move in</Button>
|
|
223
227
|
```
|
|
224
228
|
|
|
225
229
|
#### Input
|
|
@@ -279,6 +283,7 @@ Advanced select component with search, multi-select, and grouping support.
|
|
|
279
283
|
- `closeOnSelect`: boolean
|
|
280
284
|
- `maxTagCount`: number (default: 3)
|
|
281
285
|
- `allowClear`: boolean (default: false; set it when the field may be emptied)
|
|
286
|
+
- `size`: 'sm' | 'md' | 'lg' (default: 'md') — `md` grows to the 44px touch target on coarse pointers; `lg` is 44px everywhere
|
|
282
287
|
|
|
283
288
|
```jsx
|
|
284
289
|
<Select
|
|
@@ -510,10 +515,10 @@ Top navigation bar with user menu and notifications.
|
|
|
510
515
|
Fixed bottom tab bar for phones (`md:hidden`). Uses the semantic `bg-surface` / `border-line` tokens, so it follows dark mode.
|
|
511
516
|
|
|
512
517
|
**Props:**
|
|
513
|
-
- `items`: Array<{ id, label, icon, onClick?, active?, badge? }>
|
|
518
|
+
- `items`: Array<{ id, label, icon, onClick?, active?, badge?, variant?, 'aria-*'?, 'data-*'? }>
|
|
514
519
|
- `className`: string
|
|
515
520
|
|
|
516
|
-
The `active` item gets a tinted primary background, `text-primary-700` and `aria-current="page"` (inactive tabs are neutral `text-muted`). Badges sit on their own item's icon. Items share the width and labels truncate, so five tabs fit a 375px screen.
|
|
521
|
+
`variant: 'action'` renders the item as a raised circular primary button (FAB), e.g. a centre "+" that opens a sheet. `aria-*` and `data-*` item keys reach the button, so an item can carry `aria-haspopup="dialog"` and `aria-expanded`. The `active` item gets a tinted primary background, `text-primary-700` and `aria-current="page"` (inactive tabs are neutral `text-muted`). Badges sit on their own item's icon. Items share the width and labels truncate, so five tabs fit a 375px screen.
|
|
517
522
|
|
|
518
523
|
```jsx
|
|
519
524
|
<FootNav
|
|
@@ -665,7 +670,7 @@ Status indicators and labels with different variants.
|
|
|
665
670
|
|
|
666
671
|
**Props:**
|
|
667
672
|
- `children`: ReactNode
|
|
668
|
-
- `variant`: 'default' | 'primary' | 'secondary' | 'success' | 'warning' | 'error' | 'outline' (default: 'default')
|
|
673
|
+
- `variant`: 'default' | 'primary' | 'secondary' | 'success' | 'warning' | 'error' | 'info' | 'outline' (default: 'default')
|
|
669
674
|
- `size`: 'sm' | 'md' | 'lg' (default: 'md')
|
|
670
675
|
- `rounded`: boolean (default: true)
|
|
671
676
|
|
|
@@ -708,7 +713,7 @@ Interaction primitives that products used to compose by hand. All are `forwardRe
|
|
|
708
713
|
|
|
709
714
|
| Component | Group | Use for |
|
|
710
715
|
|---|---|---|
|
|
711
|
-
| [`Drawer`](doc/Drawer.md) | Feedback | Side/edge sheet (`placement` right/left/top/bottom, `size` sm–full) — record peeks and editors. Same `isOpen`/`onClose` contract as `Dialog`; focus trap, Escape/backdrop close, focus restore, scroll lock; `Drawer.Header/Body/Footer` |
|
|
716
|
+
| [`Drawer`](doc/Drawer.md) | Feedback | Side/edge sheet (`placement` right/left/top/bottom, `size` sm–full) — record peeks and editors. `placement="bottom"` is a phone bottom sheet (grab `handle`, `swipeToClose`, rounded top, safe-area padding). Same `isOpen`/`onClose` contract as `Dialog`; focus trap, Escape/backdrop close, focus restore, scroll lock; `Drawer.Header/Body/Footer` |
|
|
712
717
|
| [`Popover`](doc/Popover.md) | Core | Anchored, click-triggered panel with interactive content (unlike `Tooltip`). Controlled/uncontrolled `open`, `placement` with flip, Escape/outside-click close, `aria-expanded`/`aria-controls`/`aria-haspopup="dialog"` |
|
|
713
718
|
| [`Textarea`](doc/Textarea.md) | Core | Multi-line input mirroring `Input`: `label`, `error`, `helperText`, `required`, `showCount`/`maxLength`, `autoResize`/`maxRows` |
|
|
714
719
|
| [`Slider`](doc/Slider.md) | Core | Single value or `[low, high]` range; `min`/`max`/`step`, arrows/PageUp/PageDown/Home/End, `role="slider"` with full `aria-value*` |
|
|
@@ -872,7 +877,7 @@ module.exports = {
|
|
|
872
877
|
@source "../node_modules/@dreamtree-org/twreact-ui/dist/index.esm.js";
|
|
873
878
|
```
|
|
874
879
|
|
|
875
|
-
This adds semantic utilities next to the palettes: `bg-surface`, `bg-background`, `text-foreground`, `text-muted`, `border-line`, `bg-shell`, `text-micro`, `rounded-control` and `rounded-card`. Add a brand by creating `tokens/brands/<name>.json`; it overrides only the steps and roles you list.
|
|
880
|
+
The palettes are `primary`, `secondary`, `success`, `warning`, `error`, `info` and `gray` (steps 50–950), so `bg-info-50` / `text-info-600` work out of the box; `info` is for informational and scheduled states that are not the brand accent. This adds semantic utilities next to the palettes: `bg-surface`, `bg-background`, `text-foreground`, `text-muted`, `border-line`, `bg-shell`, `text-micro`, `rounded-control` and `rounded-card`. Add a brand by creating `tokens/brands/<name>.json`; it overrides only the steps and roles you list.
|
|
876
881
|
|
|
877
882
|
**Design rules:** [`DESIGN.md`](DESIGN.md) is the rule set for product screens and AI agents: tokens only, blocks first, loading, empty and error states, 390 px, no native dialogs. It is generated from the tokens (`npm run build:tokens`).
|
|
878
883
|
|
|
@@ -896,6 +901,8 @@ function App() {
|
|
|
896
901
|
}
|
|
897
902
|
```
|
|
898
903
|
|
|
904
|
+
Surfaces such as `Card`, `Sidebar`, `Navbar`, `Table`, `FootNav` and `Dropdown` use the semantic `bg-surface` / `bg-background` / `border-line` / `text-foreground` / `text-muted` tokens, which switch under `.dark` (or `[data-theme="dark"]`). Re-theme them by overriding the `--dt-surface`, `--dt-background`, `--dt-line`, … variables.
|
|
905
|
+
|
|
899
906
|
## Examples
|
|
900
907
|
|
|
901
908
|
### Complete Form Example
|
|
@@ -1025,7 +1032,7 @@ MIT License - see [LICENSE](LICENSE) for details.
|
|
|
1025
1032
|
|
|
1026
1033
|
## Support
|
|
1027
1034
|
|
|
1028
|
-
- 📖 [
|
|
1035
|
+
- 📖 [Storybook](https://storybook.app.drm3.org)
|
|
1029
1036
|
- 🐛 [Issue Tracker](https://github.com/dreamtree-ui/dreamtree-ui/issues)
|
|
1030
1037
|
- 💬 [Discussions](https://github.com/dreamtree-ui/dreamtree-ui/discussions)
|
|
1031
1038
|
- 🌐 [Dreamtree Global](http://dreamtreeglobal.com/)
|
|
@@ -193,7 +193,11 @@ When suggesting a component or new variant value, use this exact vocabulary.
|
|
|
193
193
|
|
|
194
194
|
**Interaction primitives** — reach for these before hand-rolling the pattern:
|
|
195
195
|
|
|
196
|
-
- `Drawer` — side/edge sheet for record peeks and editors (`isOpen`, `onClose`, `title`, `placement`, `size`, `footer`); don't fake one with `Dialog size="lg"`.
|
|
196
|
+
- `Drawer` — side/edge sheet for record peeks and editors (`isOpen`, `onClose`, `title`, `placement`, `size`, `footer`); don't fake one with `Dialog size="lg"`. On phones use `placement="bottom"` (+ `swipeToClose`) as the bottom sheet: it already has a grab `handle`, rounded top and safe-area padding — don't add them with `className`.
|
|
197
|
+
- `FootNav` — phone tab bar. A centre "+" is an item with `variant: 'action'` (raised primary circle); give it `'aria-haspopup': 'dialog'` and `'aria-expanded'` when it opens a sheet.
|
|
198
|
+
- `Button` as a link — `<Button href="tel:…">` or `<Button as={Link} to="/x">`; never copy Button's class string onto an `<a>`.
|
|
199
|
+
- `Select size="lg"` — 44px trigger for phone forms (`md` already grows to 44px on touch screens).
|
|
200
|
+
- `Stepper` steps take `title` (or its alias `label`). `Radio` follows the primary token by default — don't pass `radioColor` to match the brand.
|
|
197
201
|
- `Popover` — click-triggered panel with controls (`trigger={<Button>…</Button>}`, children or `({ close }) => …`); `Tooltip` is for read-only hover text only.
|
|
198
202
|
- `Textarea` — same API as `Input` plus `autoResize`/`maxRows`; never a raw `<textarea>`.
|
|
199
203
|
- `Slider` — `defaultValue={40}` for one thumb, `[low, high]` for a range; `onChangeEnd` to save after a drag.
|
package/dist/ai-schema.json
CHANGED
|
@@ -304,6 +304,7 @@
|
|
|
304
304
|
"success",
|
|
305
305
|
"warning",
|
|
306
306
|
"error",
|
|
307
|
+
"info",
|
|
307
308
|
"outline"
|
|
308
309
|
],
|
|
309
310
|
"default": "\"default\""
|
|
@@ -527,6 +528,27 @@
|
|
|
527
528
|
"submit",
|
|
528
529
|
"reset"
|
|
529
530
|
]
|
|
531
|
+
},
|
|
532
|
+
"as": {
|
|
533
|
+
"type": "ElementType",
|
|
534
|
+
"required": false,
|
|
535
|
+
"default": "\"button\""
|
|
536
|
+
},
|
|
537
|
+
"href": {
|
|
538
|
+
"type": "string",
|
|
539
|
+
"required": false
|
|
540
|
+
},
|
|
541
|
+
"target": {
|
|
542
|
+
"type": "string",
|
|
543
|
+
"required": false
|
|
544
|
+
},
|
|
545
|
+
"rel": {
|
|
546
|
+
"type": "string",
|
|
547
|
+
"required": false
|
|
548
|
+
},
|
|
549
|
+
"to": {
|
|
550
|
+
"type": "string | Record<string, unknown>",
|
|
551
|
+
"required": false
|
|
530
552
|
}
|
|
531
553
|
}
|
|
532
554
|
},
|
|
@@ -1098,6 +1120,16 @@
|
|
|
1098
1120
|
"initialFocusRef": {
|
|
1099
1121
|
"type": "RefObject",
|
|
1100
1122
|
"required": false
|
|
1123
|
+
},
|
|
1124
|
+
"handle": {
|
|
1125
|
+
"type": "boolean",
|
|
1126
|
+
"required": false,
|
|
1127
|
+
"default": "true for placement=\"bottom\", else false"
|
|
1128
|
+
},
|
|
1129
|
+
"swipeToClose": {
|
|
1130
|
+
"type": "boolean",
|
|
1131
|
+
"required": false,
|
|
1132
|
+
"default": "false"
|
|
1101
1133
|
}
|
|
1102
1134
|
}
|
|
1103
1135
|
},
|
|
@@ -1906,7 +1938,7 @@
|
|
|
1906
1938
|
"radioColor": {
|
|
1907
1939
|
"type": "string",
|
|
1908
1940
|
"required": false,
|
|
1909
|
-
"default": "\"
|
|
1941
|
+
"default": "\"rgb(var(--dt-primary-600))\""
|
|
1910
1942
|
},
|
|
1911
1943
|
"ariaLabel": {
|
|
1912
1944
|
"type": "string",
|
|
@@ -2264,6 +2296,16 @@
|
|
|
2264
2296
|
"renderGroupLabel": {
|
|
2265
2297
|
"type": "(label: string) => ReactNode",
|
|
2266
2298
|
"required": false
|
|
2299
|
+
},
|
|
2300
|
+
"size": {
|
|
2301
|
+
"type": "enum",
|
|
2302
|
+
"required": false,
|
|
2303
|
+
"values": [
|
|
2304
|
+
"sm",
|
|
2305
|
+
"md",
|
|
2306
|
+
"lg"
|
|
2307
|
+
],
|
|
2308
|
+
"default": "\"md\""
|
|
2267
2309
|
}
|
|
2268
2310
|
}
|
|
2269
2311
|
},
|
|
@@ -2692,7 +2734,7 @@
|
|
|
2692
2734
|
"forwardRef": true,
|
|
2693
2735
|
"props": {
|
|
2694
2736
|
"steps": {
|
|
2695
|
-
"type": "
|
|
2737
|
+
"type": "Array",
|
|
2696
2738
|
"required": true,
|
|
2697
2739
|
"default": "[]"
|
|
2698
2740
|
},
|
|
@@ -2936,7 +2978,8 @@
|
|
|
2936
2978
|
},
|
|
2937
2979
|
"theme": {
|
|
2938
2980
|
"type": "TableTheme",
|
|
2939
|
-
"required": false
|
|
2981
|
+
"required": false,
|
|
2982
|
+
"default": "see below"
|
|
2940
2983
|
},
|
|
2941
2984
|
"responsiveBreakpoint": {
|
|
2942
2985
|
"type": "number",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Button.d.ts","sourceRoot":"","sources":["../../../src/components/core/Button.jsx"],"names":[],"mappings":";AAIA,
|
|
1
|
+
{"version":3,"file":"Button.d.ts","sourceRoot":"","sources":["../../../src/components/core/Button.jsx"],"names":[],"mappings":";AAIA,gFAkEG;kBAtE+B,OAAO"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Radio.d.ts","sourceRoot":"","sources":["../../../src/components/core/Radio.jsx"],"names":[],"mappings":";AAYA,+
|
|
1
|
+
{"version":3,"file":"Radio.d.ts","sourceRoot":"","sources":["../../../src/components/core/Radio.jsx"],"names":[],"mappings":";AAYA,+EAsIG;kBAjJgD,OAAO"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Select.d.ts","sourceRoot":"","sources":["../../../src/components/core/Select.jsx"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"Select.d.ts","sourceRoot":"","sources":["../../../src/components/core/Select.jsx"],"names":[],"mappings":";AA8GA,gFAwzBE;kBA95BK,OAAO"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MobileCard.d.ts","sourceRoot":"","sources":["../../../../src/components/core/Table/MobileCard.jsx"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"MobileCard.d.ts","sourceRoot":"","sources":["../../../../src/components/core/Table/MobileCard.jsx"],"names":[],"mappings":";AAYA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4CAsOC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TableRow.d.ts","sourceRoot":"","sources":["../../../../src/components/core/Table/TableRow.jsx"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"TableRow.d.ts","sourceRoot":"","sources":["../../../../src/components/core/Table/TableRow.jsx"],"names":[],"mappings":";AAYA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4CA+RC"}
|
|
@@ -1,4 +1,16 @@
|
|
|
1
1
|
export function getRowKey(row: any, globalIndex: any): string;
|
|
2
|
+
export function getStripeProps(stripe: any): {
|
|
3
|
+
className?: undefined;
|
|
4
|
+
style?: undefined;
|
|
5
|
+
} | {
|
|
6
|
+
className: any;
|
|
7
|
+
style?: undefined;
|
|
8
|
+
} | {
|
|
9
|
+
style: {
|
|
10
|
+
backgroundColor: any;
|
|
11
|
+
};
|
|
12
|
+
className?: undefined;
|
|
13
|
+
};
|
|
2
14
|
export function rowHasDetails(hasDetails: any, row: any, index: any): boolean;
|
|
3
15
|
export function getActionLabelText(action: any): any;
|
|
4
16
|
export function mergeDefaultActions(overrides: any[], defaults: any[]): any[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../../src/components/core/Table/helpers.js"],"names":[],"mappings":"AAGO,8DAMN;AAaM,8EACqE;AAMrE,qDAGG;AAcH,8EAmBN;AAuBM,wCALI,gBAAc,OACd,MAAM,SACN,MAAM,GACJ;IAAE,aAAa,QAAQ;IAAC,WAAW,QAAO;CAAE,CAyBxD"}
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../../src/components/core/Table/helpers.js"],"names":[],"mappings":"AAGO,8DAMN;AAOM;;;;;;;;;;;EAKN;AAaM,8EACqE;AAMrE,qDAGG;AAcH,8EAmBN;AAuBM,wCALI,gBAAc,OACd,MAAM,SACN,MAAM,GACJ;IAAE,aAAa,QAAQ;IAAC,WAAW,QAAO;CAAE,CAyBxD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Dialog.d.ts","sourceRoot":"","sources":["../../../src/components/feedback/Dialog.jsx"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"Dialog.d.ts","sourceRoot":"","sources":["../../../src/components/feedback/Dialog.jsx"],"names":[],"mappings":";AAoCA,gFA0JG;kBA9LsC,OAAO"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Drawer.d.ts","sourceRoot":"","sources":["../../../src/components/feedback/Drawer.jsx"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"Drawer.d.ts","sourceRoot":"","sources":["../../../src/components/feedback/Drawer.jsx"],"names":[],"mappings":";AAqCA,gFAqHG;kBA1JkC,OAAO"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FootNav.d.ts","sourceRoot":"","sources":["../../../src/components/navigation/FootNav.jsx"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"FootNav.d.ts","sourceRoot":"","sources":["../../../src/components/navigation/FootNav.jsx"],"names":[],"mappings":";AAmBA,iFA0DG;kBA7Ee,OAAO"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Badge.d.ts","sourceRoot":"","sources":["../../../src/components/utility/Badge.jsx"],"names":[],"mappings":";AAGA,+
|
|
1
|
+
{"version":3,"file":"Badge.d.ts","sourceRoot":"","sources":["../../../src/components/utility/Badge.jsx"],"names":[],"mappings":";AAGA,+EA8CG;kBAjDe,OAAO"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Stepper.d.ts","sourceRoot":"","sources":["../../../src/components/utility/Stepper.jsx"],"names":[],"mappings":";AAIA,
|
|
1
|
+
{"version":3,"file":"Stepper.d.ts","sourceRoot":"","sources":["../../../src/components/utility/Stepper.jsx"],"names":[],"mappings":";AAIA,iFAuIG;kBA3Ie,OAAO"}
|
|
@@ -10,7 +10,7 @@ var _excluded = ["status", "map", "tone", "icon", "children", "className"];
|
|
|
10
10
|
// One map from domain state to tone + human label; unknown states are humanized, never shown raw.
|
|
11
11
|
var TONE_TO_VARIANT = {
|
|
12
12
|
neutral: 'secondary',
|
|
13
|
-
info: '
|
|
13
|
+
info: 'info',
|
|
14
14
|
success: 'success',
|
|
15
15
|
warning: 'warning',
|
|
16
16
|
danger: 'error',
|
|
@@ -5,7 +5,7 @@ import { forwardRef } from 'react';
|
|
|
5
5
|
import { cn } from '../../utils/cn.js';
|
|
6
6
|
import { Loader2 } from 'lucide-react';
|
|
7
7
|
|
|
8
|
-
var _excluded = ["className", "variant", "size", "disabled", "loading", "children", "leftIcon", "rightIcon", "fullWidth"];
|
|
8
|
+
var _excluded = ["className", "variant", "size", "disabled", "loading", "children", "leftIcon", "rightIcon", "fullWidth", "as", "onClick"];
|
|
9
9
|
var Button = /*#__PURE__*/forwardRef(function (_ref, ref) {
|
|
10
10
|
var className = _ref.className,
|
|
11
11
|
_ref$variant = _ref.variant,
|
|
@@ -18,12 +18,19 @@ var Button = /*#__PURE__*/forwardRef(function (_ref, ref) {
|
|
|
18
18
|
leftIcon = _ref.leftIcon,
|
|
19
19
|
rightIcon = _ref.rightIcon,
|
|
20
20
|
fullWidth = _ref.fullWidth,
|
|
21
|
+
as = _ref.as,
|
|
22
|
+
onClick = _ref.onClick,
|
|
21
23
|
props = _objectWithoutProperties(_ref, _excluded);
|
|
22
|
-
|
|
24
|
+
// `as` renders any element or component (an <a>, a router Link) with the
|
|
25
|
+
// Button's look; a bare `href` implies an <a>.
|
|
26
|
+
var Component = as || (props.href !== undefined ? 'a' : 'button');
|
|
27
|
+
var isNativeButton = Component === 'button';
|
|
28
|
+
var isDisabled = disabled || loading;
|
|
29
|
+
var baseClasses = cn('inline-flex items-center justify-center rounded-md font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none aria-disabled:opacity-50 aria-disabled:pointer-events-none', {
|
|
23
30
|
// Variants
|
|
24
31
|
'bg-primary-600 text-white hover:bg-primary-700 focus:ring-primary-500': variant === 'primary',
|
|
25
32
|
'bg-secondary-100 text-secondary-900 hover:bg-secondary-200 focus:ring-secondary-500': variant === 'secondary',
|
|
26
|
-
'bg-transparent border border-gray-300 hover:bg-gray-50 focus:ring-primary-500': variant === 'outline',
|
|
33
|
+
'bg-transparent border border-gray-300 hover:bg-gray-50 focus:ring-primary-500 dark:border-gray-600 dark:text-gray-100 dark:hover:bg-gray-800 dark:focus:ring-offset-gray-900': variant === 'outline',
|
|
27
34
|
'bg-transparent text-primary-600 hover:bg-primary-50 focus:ring-primary-500': variant === 'ghost',
|
|
28
35
|
'bg-error-600 text-white hover:bg-error-700 focus:ring-error-500': variant === 'destructive',
|
|
29
36
|
'bg-success-600 text-white hover:bg-success-700 focus:ring-success-500': variant === 'success',
|
|
@@ -38,10 +45,20 @@ var Button = /*#__PURE__*/forwardRef(function (_ref, ref) {
|
|
|
38
45
|
// Full width
|
|
39
46
|
'w-full': fullWidth
|
|
40
47
|
}, className);
|
|
41
|
-
return jsxs(
|
|
48
|
+
return jsxs(Component, _objectSpread2(_objectSpread2(_objectSpread2({
|
|
42
49
|
ref: ref,
|
|
43
|
-
className: baseClasses
|
|
44
|
-
|
|
50
|
+
className: baseClasses
|
|
51
|
+
}, isNativeButton ? {
|
|
52
|
+
disabled: isDisabled
|
|
53
|
+
}
|
|
54
|
+
// Links can't be `disabled`: announce it and swallow the click instead.
|
|
55
|
+
: isDisabled && {
|
|
56
|
+
'aria-disabled': true,
|
|
57
|
+
tabIndex: -1
|
|
58
|
+
}), {}, {
|
|
59
|
+
onClick: !isNativeButton && isDisabled ? function (e) {
|
|
60
|
+
return e.preventDefault();
|
|
61
|
+
} : onClick
|
|
45
62
|
}, props), {}, {
|
|
46
63
|
children: [loading && jsx(Loader2, {
|
|
47
64
|
className: "mr-2 h-4 w-4 animate-spin"
|
|
@@ -51,7 +51,8 @@ var Radio = /*#__PURE__*/forwardRef(function Radio(_ref, ref) {
|
|
|
51
51
|
props = _objectWithoutProperties(_ref, _excluded);
|
|
52
52
|
var autoId = useId();
|
|
53
53
|
var inputId = id || "".concat(autoId, "-radio");
|
|
54
|
-
|
|
54
|
+
// Default to the brand's primary token so the radio follows theming.
|
|
55
|
+
var accentColor = radioColor || "rgb(var(--dt-primary-600))";
|
|
55
56
|
var _useState = useState(!!defaultChecked),
|
|
56
57
|
_useState2 = _slicedToArray(_useState, 2),
|
|
57
58
|
internalChecked = _useState2[0],
|
|
@@ -109,7 +110,7 @@ var Radio = /*#__PURE__*/forwardRef(function Radio(_ref, ref) {
|
|
|
109
110
|
"--radio-accent": accentColor
|
|
110
111
|
},
|
|
111
112
|
children: jsx("span", {
|
|
112
|
-
className: cn("flex items-center justify-center rounded-full border transition-colors duration-150 ease-in-out border-slate-300", sizeClasses.outer, disabled ? "bg-slate-100" : "bg-white", isChecked ? "shadow-inner" : ""),
|
|
113
|
+
className: cn("flex items-center justify-center rounded-full border transition-colors duration-150 ease-in-out border-slate-300 dark:border-gray-600", sizeClasses.outer, disabled ? "bg-slate-100 dark:bg-gray-800" : "bg-white dark:bg-gray-900", isChecked ? "shadow-inner" : ""),
|
|
113
114
|
children: jsx("span", {
|
|
114
115
|
"aria-hidden": true,
|
|
115
116
|
className: cn("rounded-full transform transition-all duration-200 ease-out", sizeClasses.dot),
|
|
@@ -7,7 +7,7 @@ import { cn } from '../../utils/cn.js';
|
|
|
7
7
|
import { useLatestRef } from '../../hooks/useLatestRef.js';
|
|
8
8
|
import { ChevronDown, X, Check, Search, Plus } from 'lucide-react';
|
|
9
9
|
|
|
10
|
-
var _excluded = ["options", "value", "onChange", "placeholder", "label", "error", "helperText", "disabled", "required", "multiSelect", "searchable", "grouped", "onMenuItemRender", "className", "allowClear", "creatable", "onCreateOption", "onSearch", "loading", "selectAllOption", "closeOnSelect", "maxTagCount", "renderGroupLabel", "name"];
|
|
10
|
+
var _excluded = ["options", "value", "onChange", "placeholder", "label", "error", "helperText", "disabled", "required", "multiSelect", "searchable", "grouped", "onMenuItemRender", "className", "allowClear", "creatable", "onCreateOption", "onSearch", "loading", "selectAllOption", "closeOnSelect", "maxTagCount", "renderGroupLabel", "name", "size"];
|
|
11
11
|
/**
|
|
12
12
|
* Enhanced Select component (debounce removed)
|
|
13
13
|
* - Supports single and multi select
|
|
@@ -106,6 +106,14 @@ var highlight = function highlight() {
|
|
|
106
106
|
}), label.slice(idx + term.length)]
|
|
107
107
|
});
|
|
108
108
|
};
|
|
109
|
+
// Trigger sizes. min-h (not h) so multi-select tags can wrap. `md` keeps its
|
|
110
|
+
// desktop look but grows to the 44px touch target on coarse pointers; `lg` is
|
|
111
|
+
// 44px everywhere.
|
|
112
|
+
var SIZE_CLASSES = {
|
|
113
|
+
sm: "min-h-8 px-2.5 py-1 text-xs",
|
|
114
|
+
md: "min-h-[38px] px-3 py-2 text-sm [@media(pointer:coarse)]:min-h-11",
|
|
115
|
+
lg: "min-h-11 px-4 py-2.5 text-base"
|
|
116
|
+
};
|
|
109
117
|
var Select = /*#__PURE__*/React.forwardRef(function (_ref, forwardedRef) {
|
|
110
118
|
var _ref$options = _ref.options,
|
|
111
119
|
options = _ref$options === void 0 ? [] : _ref$options,
|
|
@@ -142,6 +150,8 @@ var Select = /*#__PURE__*/React.forwardRef(function (_ref, forwardedRef) {
|
|
|
142
150
|
maxTagCount = _ref$maxTagCount === void 0 ? 3 : _ref$maxTagCount,
|
|
143
151
|
renderGroupLabel = _ref.renderGroupLabel,
|
|
144
152
|
name = _ref.name,
|
|
153
|
+
_ref$size = _ref.size,
|
|
154
|
+
size = _ref$size === void 0 ? "md" : _ref$size,
|
|
145
155
|
props = _objectWithoutProperties(_ref, _excluded);
|
|
146
156
|
var _useState = useState(false),
|
|
147
157
|
_useState2 = _slicedToArray(_useState, 2),
|
|
@@ -712,7 +722,7 @@ var Select = /*#__PURE__*/React.forwardRef(function (_ref, forwardedRef) {
|
|
|
712
722
|
"aria-labelledby": label ? "".concat(labelId, " ").concat(valueId) : valueId,
|
|
713
723
|
"aria-describedby": describedBy,
|
|
714
724
|
"aria-invalid": error ? true : undefined,
|
|
715
|
-
className: cn("flex w-full items-center justify-between rounded-md border border-gray-300
|
|
725
|
+
className: cn("flex w-full items-center justify-between rounded-md border border-gray-300 focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-transparent disabled:cursor-not-allowed disabled:opacity-50", SIZE_CLASSES[size] || SIZE_CLASSES.md, {
|
|
716
726
|
"border-error-500 focus:ring-error-500": error,
|
|
717
727
|
"text-primary-500": !selectedOptions.length,
|
|
718
728
|
"pr-14": showClearButton
|
|
@@ -6,8 +6,8 @@ import { createPortal } from 'react-dom';
|
|
|
6
6
|
import { cn } from '../../../utils/cn.js';
|
|
7
7
|
import { useLatestRef } from '../../../hooks/useLatestRef.js';
|
|
8
8
|
|
|
9
|
-
var DEFAULT_MENU_BG = "bg-
|
|
10
|
-
var DEFAULT_MENU_ITEM_HOVER = "opacity-75 hover:opacity-100 hover:bg-gray-100/80 active:bg-gray-200/80";
|
|
9
|
+
var DEFAULT_MENU_BG = "bg-surface border border-line shadow-xl";
|
|
10
|
+
var DEFAULT_MENU_ITEM_HOVER = "opacity-75 hover:opacity-100 hover:bg-gray-100/80 active:bg-gray-200/80 dark:hover:bg-gray-800 dark:active:bg-gray-700";
|
|
11
11
|
function ActionMenu(_ref) {
|
|
12
12
|
var _theme$menuBg, _theme$menuItemHover;
|
|
13
13
|
var _ref$actions = _ref.actions,
|
|
@@ -211,7 +211,7 @@ function ActionMenu(_ref) {
|
|
|
211
211
|
children: jsx("div", {
|
|
212
212
|
className: "p-1.5 space-y-0.5",
|
|
213
213
|
children: !Array.isArray(actions) || actions.length === 0 ? jsx("div", {
|
|
214
|
-
className: "px-3 py-2 text-sm text-
|
|
214
|
+
className: "px-3 py-2 text-sm text-muted italic",
|
|
215
215
|
children: "No actions"
|
|
216
216
|
}) : actions.map(function (action, idx) {
|
|
217
217
|
var _action$name;
|
|
@@ -222,7 +222,7 @@ function ActionMenu(_ref) {
|
|
|
222
222
|
type: "button",
|
|
223
223
|
disabled: isDisabled,
|
|
224
224
|
"aria-disabled": isDisabled || undefined,
|
|
225
|
-
className: cn("w-full text-left px-3 py-2 text-sm flex items-center gap-2.5 rounded-lg transition-colors font-medium", isDisabled ? "opacity-50 cursor-not-allowed text-
|
|
225
|
+
className: cn("w-full text-left px-3 py-2 text-sm flex items-center gap-2.5 rounded-lg transition-colors font-medium", isDisabled ? "opacity-50 cursor-not-allowed text-muted" : ["text-foreground", menuItemHover, isFocused ? "bg-gray-100 text-gray-900 ring-1 ring-gray-300 dark:bg-gray-800 dark:text-foreground dark:ring-gray-600" : ""]),
|
|
226
226
|
onMouseEnter: function onMouseEnter() {
|
|
227
227
|
return !isDisabled && setFocusedIndex(idx);
|
|
228
228
|
},
|
|
@@ -234,7 +234,7 @@ function ActionMenu(_ref) {
|
|
|
234
234
|
},
|
|
235
235
|
children: action.render ? action.render(row) : jsxs(Fragment, {
|
|
236
236
|
children: [action.icon && jsx("span", {
|
|
237
|
-
className: "inline-flex text-
|
|
237
|
+
className: "inline-flex text-muted flex-shrink-0",
|
|
238
238
|
children: action.icon
|
|
239
239
|
}), jsx("span", {
|
|
240
240
|
className: "truncate",
|
|
@@ -56,7 +56,7 @@ function FieldInput(_ref) {
|
|
|
56
56
|
onClick: stopProp,
|
|
57
57
|
onMouseDown: stopProp,
|
|
58
58
|
placeholder: "Enter ".concat(column.label || column.key, "..."),
|
|
59
|
-
className: cn("w-full px-2 py-1 text-sm border rounded outline-none transition-all focus:ring-2 focus:ring-primary-500 bg-
|
|
59
|
+
className: cn("w-full px-2 py-1 text-sm border rounded outline-none transition-all focus:ring-2 focus:ring-primary-500 bg-surface text-foreground resize-y min-h-[2.5rem]", className)
|
|
60
60
|
});
|
|
61
61
|
}
|
|
62
62
|
// Select / Dropdown
|
|
@@ -76,7 +76,7 @@ function FieldInput(_ref) {
|
|
|
76
76
|
onKeyDown: onKeyDown,
|
|
77
77
|
onClick: stopProp,
|
|
78
78
|
onMouseDown: stopProp,
|
|
79
|
-
className: cn("w-full px-2 py-1 text-sm border rounded outline-none focus:ring-2 focus:ring-primary-500 bg-
|
|
79
|
+
className: cn("w-full px-2 py-1 text-sm border rounded outline-none focus:ring-2 focus:ring-primary-500 bg-surface text-foreground", className),
|
|
80
80
|
children: [jsxs("option", {
|
|
81
81
|
value: "",
|
|
82
82
|
children: ["Select ", column.label || column.key]
|
|
@@ -119,7 +119,7 @@ function FieldInput(_ref) {
|
|
|
119
119
|
onKeyDown: onKeyDown,
|
|
120
120
|
onClick: stopProp,
|
|
121
121
|
onMouseDown: stopProp,
|
|
122
|
-
className: cn("w-full px-2 py-1 text-sm border rounded outline-none focus:ring-2 focus:ring-primary-500 bg-
|
|
122
|
+
className: cn("w-full px-2 py-1 text-sm border rounded outline-none focus:ring-2 focus:ring-primary-500 bg-surface text-foreground", className)
|
|
123
123
|
});
|
|
124
124
|
}
|
|
125
125
|
// Number
|
|
@@ -135,7 +135,7 @@ function FieldInput(_ref) {
|
|
|
135
135
|
onClick: stopProp,
|
|
136
136
|
onMouseDown: stopProp,
|
|
137
137
|
placeholder: "Enter ".concat(column.label || column.key, "..."),
|
|
138
|
-
className: cn("w-full px-2 py-1 text-sm border rounded outline-none focus:ring-2 focus:ring-primary-500 bg-
|
|
138
|
+
className: cn("w-full px-2 py-1 text-sm border rounded outline-none focus:ring-2 focus:ring-primary-500 bg-surface text-foreground", className)
|
|
139
139
|
});
|
|
140
140
|
}
|
|
141
141
|
// Default: Text
|
|
@@ -150,7 +150,7 @@ function FieldInput(_ref) {
|
|
|
150
150
|
onClick: stopProp,
|
|
151
151
|
onMouseDown: stopProp,
|
|
152
152
|
placeholder: "Enter ".concat(column.label || column.key, "..."),
|
|
153
|
-
className: cn("w-full px-2 py-1 text-sm border rounded outline-none focus:ring-2 focus:ring-primary-500 bg-
|
|
153
|
+
className: cn("w-full px-2 py-1 text-sm border rounded outline-none focus:ring-2 focus:ring-primary-500 bg-surface text-foreground", className)
|
|
154
154
|
});
|
|
155
155
|
}
|
|
156
156
|
|
|
@@ -4,7 +4,7 @@ import React from 'react';
|
|
|
4
4
|
import { cn } from '../../../utils/cn.js';
|
|
5
5
|
import { MoreVertical } from 'lucide-react';
|
|
6
6
|
import ActionMenu from './ActionMenu.js';
|
|
7
|
-
import { getRowKey, resolveActions, rowHasDetails, getActionLabelText } from './helpers.js';
|
|
7
|
+
import { getRowKey, resolveActions, rowHasDetails, getActionLabelText, getStripeProps } from './helpers.js';
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Mobile card view for a single table row
|
|
@@ -61,11 +61,10 @@ function MobileCard(_ref) {
|
|
|
61
61
|
var hasActions = withAction && (inlineActions.length > 0 || menuActions.length > 0);
|
|
62
62
|
var showHeader = showDetailsToggle || selectable || showSerial || hasActions;
|
|
63
63
|
var stripeBg = stripedRows && !isSelected && Array.isArray(stripedColors) && stripedColors.length > 0 ? stripedColors[globalIndex % stripedColors.length] : undefined;
|
|
64
|
+
var stripeProps = getStripeProps(stripeBg);
|
|
64
65
|
return jsxs("div", {
|
|
65
|
-
style:
|
|
66
|
-
|
|
67
|
-
} : undefined,
|
|
68
|
-
className: cn("border rounded-lg mb-3 shadow-sm overflow-hidden transition-all duration-200", {
|
|
66
|
+
style: stripeProps.style,
|
|
67
|
+
className: cn(stripeProps.className, "border border-line rounded-lg mb-3 shadow-sm overflow-hidden transition-all duration-200", {
|
|
69
68
|
"cursor-pointer": !!onRowClick,
|
|
70
69
|
"bg-primary-50 border-primary-200": isSelected,
|
|
71
70
|
"hover:shadow-md": !isSelected
|
|
@@ -74,7 +73,7 @@ function MobileCard(_ref) {
|
|
|
74
73
|
return onRowClick === null || onRowClick === void 0 ? void 0 : onRowClick(row, globalIndex);
|
|
75
74
|
},
|
|
76
75
|
children: [showHeader && jsxs("div", {
|
|
77
|
-
className: "flex items-center justify-between p-4 border-b bg-
|
|
76
|
+
className: "flex items-center justify-between p-4 border-b border-line bg-background",
|
|
78
77
|
children: [jsxs("div", {
|
|
79
78
|
className: "flex items-center gap-3",
|
|
80
79
|
children: [showDetailsToggle && jsx("button", {
|
|
@@ -85,7 +84,7 @@ function MobileCard(_ref) {
|
|
|
85
84
|
},
|
|
86
85
|
"aria-expanded": isExpanded,
|
|
87
86
|
"aria-label": isExpanded ? "Collapse row details" : "Expand row details",
|
|
88
|
-
className: "p-1 rounded hover:bg-gray-200",
|
|
87
|
+
className: "p-1 rounded hover:bg-gray-200 dark:hover:bg-gray-700",
|
|
89
88
|
children: isExpanded ? "▾" : "▸"
|
|
90
89
|
}), selectable && jsx("input", {
|
|
91
90
|
type: "checkbox",
|
|
@@ -119,7 +118,7 @@ function MobileCard(_ref) {
|
|
|
119
118
|
if (action.disabled) return;
|
|
120
119
|
handleOnAction(action, row);
|
|
121
120
|
},
|
|
122
|
-
className: cn("p-1.5 rounded", action.disabled ? "opacity-50 cursor-not-allowed" : "hover:bg-gray-200"),
|
|
121
|
+
className: cn("p-1.5 rounded", action.disabled ? "opacity-50 cursor-not-allowed" : "hover:bg-gray-200 dark:hover:bg-gray-700"),
|
|
123
122
|
children: action.render ? action.render(row) : (_action$icon = action.icon) !== null && _action$icon !== void 0 ? _action$icon : jsx("span", {
|
|
124
123
|
className: "text-xs",
|
|
125
124
|
children: actionLabel
|
|
@@ -136,7 +135,7 @@ function MobileCard(_ref) {
|
|
|
136
135
|
return toggleActions(e, actionCellKey, row);
|
|
137
136
|
},
|
|
138
137
|
"aria-expanded": activeActionRowKey === actionCellKey,
|
|
139
|
-
className: "p-1.5 rounded hover:bg-gray-200",
|
|
138
|
+
className: "p-1.5 rounded hover:bg-gray-200 dark:hover:bg-gray-700",
|
|
140
139
|
title: "Actions",
|
|
141
140
|
"aria-label": "Actions",
|
|
142
141
|
children: jsx(MoreVertical, {
|
|
@@ -178,7 +177,7 @@ function MobileCard(_ref) {
|
|
|
178
177
|
}, column.key);
|
|
179
178
|
})
|
|
180
179
|
}), showDetailsToggle && isExpanded && DetailsComponent && jsx("div", {
|
|
181
|
-
className: "border-t bg-
|
|
180
|
+
className: "border-t border-line bg-background p-4",
|
|
182
181
|
children: jsx(DetailsComponent, {
|
|
183
182
|
row: row,
|
|
184
183
|
index: globalIndex
|
|
@@ -19,7 +19,7 @@ function MobileFilters(_ref) {
|
|
|
19
19
|
handleFilter = _ref.handleFilter;
|
|
20
20
|
var idPrefix = React.useId();
|
|
21
21
|
return jsxs("div", {
|
|
22
|
-
className: "mb-4 p-3 bg-
|
|
22
|
+
className: "mb-4 p-3 bg-background rounded-lg",
|
|
23
23
|
children: [jsxs("div", {
|
|
24
24
|
className: "flex items-center justify-between mb-3",
|
|
25
25
|
children: [jsx("h3", {
|
|
@@ -9,7 +9,7 @@ import { ChevronsLeft, ChevronLeft, ChevronRight, ChevronsRight } from 'lucide-r
|
|
|
9
9
|
* Pagination controls component for the table
|
|
10
10
|
* Supports both header (icon-only) and footer (with page numbers) variants
|
|
11
11
|
*/
|
|
12
|
-
var DEFAULT_ROW_HOVER = "bg-
|
|
12
|
+
var DEFAULT_ROW_HOVER = "bg-background";
|
|
13
13
|
// Header pagination (compact, icon-based)
|
|
14
14
|
function PaginationHeader(_ref) {
|
|
15
15
|
var _theme$rowHover;
|