@neuronection/assistant-ui 0.2.0 → 0.4.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.
- package/CHANGELOG.md +56 -0
- package/README.md +26 -5
- package/dist/breadcrumbs.d.ts +24 -0
- package/dist/breadcrumbs.js +3 -0
- package/dist/breadcrumbs.js.map +1 -0
- package/dist/chip-input.d.ts +14 -0
- package/dist/chip-input.js +3 -0
- package/dist/chip-input.js.map +1 -0
- package/dist/chip-list.d.ts +15 -0
- package/dist/chip-list.js +3 -0
- package/dist/chip-list.js.map +1 -0
- package/dist/chunk-5AVBKEDQ.js +74 -0
- package/dist/chunk-5AVBKEDQ.js.map +1 -0
- package/dist/{chunk-GPIN2ITX.js → chunk-5HXDKOBY.js} +24 -7
- package/dist/chunk-5HXDKOBY.js.map +1 -0
- package/dist/chunk-5X3RYDPC.js +54 -0
- package/dist/chunk-5X3RYDPC.js.map +1 -0
- package/dist/chunk-CZ2BL2ZL.js +89 -0
- package/dist/chunk-CZ2BL2ZL.js.map +1 -0
- package/dist/chunk-MEBOS2FX.js +359 -0
- package/dist/chunk-MEBOS2FX.js.map +1 -0
- package/dist/chunk-TFS2NUET.js +66 -0
- package/dist/chunk-TFS2NUET.js.map +1 -0
- package/dist/chunk-TPLQL62V.js +124 -0
- package/dist/chunk-TPLQL62V.js.map +1 -0
- package/dist/chunk-UIUALJNR.js +110 -0
- package/dist/chunk-UIUALJNR.js.map +1 -0
- package/dist/chunk-WPO6CDA4.js +92 -0
- package/dist/chunk-WPO6CDA4.js.map +1 -0
- package/dist/chunk-XLD2BPTT.js +82 -0
- package/dist/chunk-XLD2BPTT.js.map +1 -0
- package/dist/copy-button.d.ts +14 -0
- package/dist/copy-button.js +3 -0
- package/dist/copy-button.js.map +1 -0
- package/dist/date-picker.d.ts +27 -0
- package/dist/date-picker.js +3 -0
- package/dist/date-picker.js.map +1 -0
- package/dist/form-modal.d.ts +6 -1
- package/dist/form-modal.js +1 -1
- package/dist/index.d.ts +10 -2
- package/dist/index.js +20 -11
- package/dist/modal.d.ts +23 -1
- package/dist/modal.js +1 -0
- package/dist/range-bar.d.ts +15 -0
- package/dist/range-bar.js +3 -0
- package/dist/range-bar.js.map +1 -0
- package/dist/scale-slider.d.ts +18 -0
- package/dist/scale-slider.js +3 -0
- package/dist/scale-slider.js.map +1 -0
- package/dist/styles.css +1 -1
- package/dist/table.d.ts +10 -0
- package/dist/table.js +3 -0
- package/dist/table.js.map +1 -0
- package/package.json +36 -2
- package/dist/chunk-GPIN2ITX.js.map +0 -1
- package/dist/chunk-IFNT6JSQ.js +0 -3
- package/dist/chunk-IFNT6JSQ.js.map +0 -1
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# @neuronection/assistant-ui
|
|
2
|
+
|
|
3
|
+
## 0.4.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [`5b2ff4c`](https://github.com/neuronection/assistant-ui/commit/5b2ff4cc6304c90fa8b15497fd554fd0a14ced21) Thanks [@constLiakos](https://github.com/constLiakos)! - Phase-3 groundwork for health-assistant adoption: `FormModal` gains
|
|
8
|
+
`headerActions`, `onReject`/`rejectLabel`, `hideFooter` and `bodyClassName`
|
|
9
|
+
(health's HITL flows need them); new `CopyButton` (clipboard with legacy
|
|
10
|
+
fallback, copied state, `onCopied`/`onCopyError` callbacks — apps own
|
|
11
|
+
toasts/i18n) and `Breadcrumbs` (router-free: `linkComponent` prop for SPA
|
|
12
|
+
links); `themes/health.css` now matches health's real blue-600 accent with a
|
|
13
|
+
`.dark` token block for its class-based dark mode. New `PanelModal`:
|
|
14
|
+
header (icon/title/actions/close) + scrollable body + sticky footer,
|
|
15
|
+
full-screen on mobile — the shared shape both career and health used as
|
|
16
|
+
their hand-rolled `Modal`. `DatePicker` gains `variant="unstyled"` for
|
|
17
|
+
inline dense usage.
|
|
18
|
+
|
|
19
|
+
## 0.3.0
|
|
20
|
+
|
|
21
|
+
### Minor Changes
|
|
22
|
+
|
|
23
|
+
- [`e8a56d3`](https://github.com/neuronection/assistant-ui/commit/e8a56d33427fc2e8e03784fe7959037f24efb95a) Thanks [@constLiakos](https://github.com/constLiakos)! - Add the six components career-assistant's Phase-2 adoption needs, all shared
|
|
24
|
+
with health-assistant (catalog T1): `ChipInput`, `ChipList` (superset with
|
|
25
|
+
variants + clickable chips), `Table` (tokenized, with empty state), `RangeBar`
|
|
26
|
+
(with optional `label`/`valueLabel`), `ScaleSlider` (+ `scaleColorForValue`),
|
|
27
|
+
and `DatePicker` (Radix popover calendar with days/months/years views, min/max,
|
|
28
|
+
allowClear, and a roving-tabindex arrow-key day grid — an a11y upgrade over
|
|
29
|
+
both app copies). New dependency: `date-fns`.
|
|
30
|
+
|
|
31
|
+
### Patch Changes
|
|
32
|
+
|
|
33
|
+
- [`e5252f2`](https://github.com/neuronection/assistant-ui/commit/e5252f26d6f8732a2f5ba4a3fe849b4df50b30c2) Thanks [@constLiakos](https://github.com/constLiakos)! - Ship CHANGELOG.md inside the published package so consuming apps (and their agents) can read what changed without visiting GitHub.
|
|
34
|
+
|
|
35
|
+
## 0.2.0
|
|
36
|
+
|
|
37
|
+
### Minor Changes
|
|
38
|
+
|
|
39
|
+
- [`ec2a8bf`](https://github.com/neuronection/assistant-ui/commit/ec2a8bf7d49bb96435990e9b8cca4d74fc31748b) Thanks [@constLiakos](https://github.com/constLiakos)! - Phase 1: 16 new modules for study-assistant full adoption
|
|
40
|
+
|
|
41
|
+
- PopoverButton: self-contained trigger+panel popover on Radix (hover-open, lazy children, closeSignal, controlled mode)
|
|
42
|
+
- InfoButton + FieldLabel: info affordances with popover help
|
|
43
|
+
- Menu: Radix DropdownMenu primitives (Menu, MenuItem, MenuContent…) + items-driven ActionMenu
|
|
44
|
+
- ContextMenu: coordinate-anchored menu with full Radix keyboard/typeahead semantics
|
|
45
|
+
- Combobox + ComboboxMulti: WAI-ARIA listbox pattern, grouping, async mode (onSearchChange + loading), multi-select, clearable
|
|
46
|
+
- FormModal: form-in-modal shell (submit/cancel/busy/disabled) on Modal primitives
|
|
47
|
+
- Wizard + Stepper: wizard state machine with per-step validation gates, modal and drawer variants; dots/labels steppers
|
|
48
|
+
- Ported from study-assistant ui/: CheckIndicator, SearchInput, ExpandableSearch, SelectionBar, ViewToggle, ErrorBanner, UndoNotice, Marquee (useMarquee/MarqueeBand/MarqueeSurface)
|
|
49
|
+
|
|
50
|
+
All components: forwardRef where DOM-emitting, semantic --as-\* tokens only, data-as hooks, English-default label props, keyboard-nav + axe tests.
|
|
51
|
+
|
|
52
|
+
## 0.1.0
|
|
53
|
+
|
|
54
|
+
### Minor Changes
|
|
55
|
+
|
|
56
|
+
- [`a211003`](https://github.com/neuronection/assistant-ui/commit/a211003348a5248f65a7995806500325408b6f92) Thanks [@constLiakos](https://github.com/constLiakos)! - Initial release (Phase 0): Button, Badge, Card, Modal, Popover, Tooltip + InfoTooltip, Input, Spinner, EmptyState, ConfirmationModal, Portal, ThemeScope and `cn()` — CSS-variable design tokens, precompiled `styles.css`, React 18/19 and Tailwind 3/4 compatible.
|
package/README.md
CHANGED
|
@@ -65,11 +65,32 @@ without configuration. Do **not** add this package to your Tailwind
|
|
|
65
65
|
|
|
66
66
|
## Components
|
|
67
67
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
[gallery](https://neuronection.github.io/assistant-ui/)
|
|
68
|
+
Every module has its own entry point (`import { Menu } from
|
|
69
|
+
'@neuronection/assistant-ui/menu'`) and everything is re-exported from the
|
|
70
|
+
package root. Authoritative props for your installed version: the `.d.ts`
|
|
71
|
+
files in the package's `dist/`. Visual reference:
|
|
72
|
+
[gallery](https://neuronection.github.io/assistant-ui/).
|
|
73
|
+
|
|
74
|
+
| Module | Exports |
|
|
75
|
+
|---|---|
|
|
76
|
+
| `button` / `badge` / `card` | `Button`, `buttonVariants` · `Badge`, `badgeVariants` · `Card`, `CardHeader/Title/Description/Content/Footer` |
|
|
77
|
+
| `modal` / `confirmation-modal` / `form-modal` | `Modal` + parts, `modalContentVariants` · `ConfirmationModal` · `FormModal` (form-in-modal shell) |
|
|
78
|
+
| `popover` / `popover-button` | compound Radix `Popover` + parts · `PopoverButton` (self-contained trigger + panel, hover-open, lazy children, `closeSignal`) |
|
|
79
|
+
| `menu` / `context-menu` | `Menu`, `MenuTrigger/Content/Item/Separator/Label`, `ActionMenu` (items-driven) · `ContextMenu` (coordinate-anchored, `{x, y, items, onClose}`) |
|
|
80
|
+
| `combobox` | `Combobox`, `ComboboxMulti` — async mode (`onSearchChange` + `loading`), grouping, full keyboard nav |
|
|
81
|
+
| `tooltip` | `Tooltip` + parts, `InfoTooltip` |
|
|
82
|
+
| `wizard` | `Wizard` (steps config + `renderStep`, per-step validation gates, modal/drawer variants), `Stepper` (dots/labels) |
|
|
83
|
+
| `input` / `search-input` / `expandable-search` | `Input` (label/hint/error wiring) · `SearchInput` · `ExpandableSearch` |
|
|
84
|
+
| `chip-input` / `chip-list` | `ChipInput` (Enter/comma commit, paste-splits, Backspace-removes) · `ChipList` (variant pills, clickable, removable) |
|
|
85
|
+
| `date-picker` | `DatePicker` (popover calendar: days/months/years views, min/max, `allowClear`, arrow-key day grid) |
|
|
86
|
+
| `range-bar` / `scale-slider` | `RangeBar` (low–high band + value dot) · `ScaleSlider` (+ `scaleColorForValue`) |
|
|
87
|
+
| `table` | `Table` (headers/rows, built-in empty state) |
|
|
88
|
+
| `check-indicator` / `selection-bar` / `view-toggle` | `CheckIndicator` (tri-state) · `SelectionBar` (bulk-select bar) · `ViewToggle` (grid/list) |
|
|
89
|
+
| `error-banner` / `undo-notice` / `empty-state` / `spinner` | presentational feedback: alert banner with `action` slot · undo toast · `EmptyState` · `Spinner` |
|
|
90
|
+
| `info-button` / `field-label` | `InfoButton` (info popover) · `FieldLabel` (label + info affordance) |
|
|
91
|
+
| `copy-button` / `breadcrumbs` | `CopyButton` (clipboard + copied state) · `Breadcrumbs` (SPA links via `linkComponent`) |
|
|
92
|
+
| `marquee` | `useMarquee`, `MarqueeSurface`, `MarqueeBand` (rubber-band selection) |
|
|
93
|
+
| `portal` / `theme-scope` / `tokens` | `Portal` · `ThemeScope` · token name lists + types |
|
|
73
94
|
|
|
74
95
|
API rules: controlled-first, `className` merges (never replaces), `asChild`
|
|
75
96
|
where it makes sense, refs forwarded everywhere, English label props with
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
|
|
3
|
+
interface BreadcrumbItem {
|
|
4
|
+
label: string;
|
|
5
|
+
href?: string;
|
|
6
|
+
icon?: React.ReactNode;
|
|
7
|
+
}
|
|
8
|
+
interface BreadcrumbLinkProps {
|
|
9
|
+
href: string;
|
|
10
|
+
className?: string;
|
|
11
|
+
title?: string;
|
|
12
|
+
'aria-label'?: string;
|
|
13
|
+
children: React.ReactNode;
|
|
14
|
+
}
|
|
15
|
+
interface BreadcrumbsProps extends React.ComponentProps<'nav'> {
|
|
16
|
+
items?: BreadcrumbItem[];
|
|
17
|
+
currentLabel?: string;
|
|
18
|
+
homeHref?: string;
|
|
19
|
+
homeLabel?: string;
|
|
20
|
+
linkComponent?: React.ComponentType<BreadcrumbLinkProps>;
|
|
21
|
+
}
|
|
22
|
+
declare const Breadcrumbs: React.ForwardRefExoticComponent<Omit<BreadcrumbsProps, "ref"> & React.RefAttributes<HTMLElement>>;
|
|
23
|
+
|
|
24
|
+
export { type BreadcrumbItem, type BreadcrumbLinkProps, Breadcrumbs, type BreadcrumbsProps };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"breadcrumbs.js"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
|
|
3
|
+
interface ChipInputProps extends Omit<React.ComponentProps<'div'>, 'onChange'> {
|
|
4
|
+
value: string[];
|
|
5
|
+
onChange: (value: string[]) => void;
|
|
6
|
+
placeholder?: string;
|
|
7
|
+
separators?: string[];
|
|
8
|
+
inputLabel?: string;
|
|
9
|
+
removeLabel?: string;
|
|
10
|
+
disabled?: boolean;
|
|
11
|
+
}
|
|
12
|
+
declare const ChipInput: React.ForwardRefExoticComponent<Omit<ChipInputProps, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
13
|
+
|
|
14
|
+
export { ChipInput, type ChipInputProps };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"chip-input.js"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
|
|
3
|
+
type ChipVariant = 'neutral' | 'primary' | 'success' | 'warning' | 'danger';
|
|
4
|
+
interface ChipListProps extends React.ComponentProps<'div'> {
|
|
5
|
+
items: ReadonlyArray<string | null | undefined>;
|
|
6
|
+
onRemove?: (item: string) => void;
|
|
7
|
+
onItemClick?: (value: string, index: number) => void;
|
|
8
|
+
variant?: ChipVariant;
|
|
9
|
+
emptyText?: string;
|
|
10
|
+
showChevron?: boolean;
|
|
11
|
+
removeLabel?: string;
|
|
12
|
+
}
|
|
13
|
+
declare const ChipList: React.ForwardRefExoticComponent<Omit<ChipListProps, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
14
|
+
|
|
15
|
+
export { ChipList, type ChipListProps, type ChipVariant };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"chip-list.js"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { cn } from './chunk-BLJWR4ZV.js';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
4
|
+
|
|
5
|
+
function pct(value, domainMin, domainMax) {
|
|
6
|
+
if (domainMax === domainMin) return 0;
|
|
7
|
+
return (value - domainMin) / (domainMax - domainMin) * 100;
|
|
8
|
+
}
|
|
9
|
+
function fmt(value) {
|
|
10
|
+
return Number.isInteger(value) ? value.toLocaleString() : value.toFixed(1).replace(/\.0$/, "");
|
|
11
|
+
}
|
|
12
|
+
var RangeBar = React.forwardRef(
|
|
13
|
+
function RangeBar2({ low, high, min, max, value, unit, label, valueLabel = "You", className, ...props }, ref) {
|
|
14
|
+
if (!Number.isFinite(low) || !Number.isFinite(high) || high <= low) {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
const span = high - low;
|
|
18
|
+
let domainMin = min ?? low - span;
|
|
19
|
+
let domainMax = max ?? high + span;
|
|
20
|
+
if (domainMin < 0 && low >= 0) {
|
|
21
|
+
const shift = -domainMin;
|
|
22
|
+
domainMin = 0;
|
|
23
|
+
domainMax += shift;
|
|
24
|
+
}
|
|
25
|
+
if (domainMax <= domainMin) domainMax = domainMin + span;
|
|
26
|
+
const left = Math.max(0, Math.min(100, pct(low, domainMin, domainMax)));
|
|
27
|
+
const right = Math.max(0, Math.min(100, pct(high, domainMin, domainMax)));
|
|
28
|
+
const valuePct = value !== null && value !== void 0 && Number.isFinite(value) ? Math.max(0, Math.min(100, pct(value, domainMin, domainMax))) : null;
|
|
29
|
+
return /* @__PURE__ */ jsxs(
|
|
30
|
+
"div",
|
|
31
|
+
{
|
|
32
|
+
ref,
|
|
33
|
+
"data-as": "range-bar",
|
|
34
|
+
className: cn("w-full", className),
|
|
35
|
+
...props,
|
|
36
|
+
children: [
|
|
37
|
+
label ? /* @__PURE__ */ jsx("p", { className: "mb-1 text-xs text-[var(--as-muted-fg)]", children: label }) : null,
|
|
38
|
+
/* @__PURE__ */ jsxs("div", { className: "relative h-3.5 w-full rounded-full bg-[var(--as-muted)]", children: [
|
|
39
|
+
/* @__PURE__ */ jsx(
|
|
40
|
+
"div",
|
|
41
|
+
{
|
|
42
|
+
className: "absolute h-full rounded-full bg-[color-mix(in_srgb,var(--as-primary)_30%,transparent)]",
|
|
43
|
+
style: { left: `${left}%`, width: `${Math.max(0, right - left)}%` },
|
|
44
|
+
title: `${label ? `${label}: ` : ""}${fmt(low)} \u2013 ${fmt(high)}${unit ? ` ${unit}` : ""}`
|
|
45
|
+
}
|
|
46
|
+
),
|
|
47
|
+
valuePct !== null ? /* @__PURE__ */ jsx(
|
|
48
|
+
"div",
|
|
49
|
+
{
|
|
50
|
+
className: "absolute top-1/2 size-2.5 -translate-x-1/2 -translate-y-1/2 rounded-full border-2 border-[var(--as-surface-raised)] bg-[var(--as-primary)] shadow-[var(--as-shadow-1)]",
|
|
51
|
+
style: { left: `${valuePct}%` },
|
|
52
|
+
title: `${valueLabel}: ${fmt(value)}${unit ? ` ${unit}` : ""}`
|
|
53
|
+
}
|
|
54
|
+
) : null
|
|
55
|
+
] }),
|
|
56
|
+
/* @__PURE__ */ jsxs("div", { className: "mt-0.5 flex justify-between text-[10px] text-[var(--as-muted-fg)]", children: [
|
|
57
|
+
/* @__PURE__ */ jsx("span", { children: fmt(domainMin) }),
|
|
58
|
+
/* @__PURE__ */ jsxs("span", { className: "font-medium", children: [
|
|
59
|
+
fmt(low),
|
|
60
|
+
" \u2013 ",
|
|
61
|
+
fmt(high),
|
|
62
|
+
unit ? ` ${unit}` : ""
|
|
63
|
+
] }),
|
|
64
|
+
/* @__PURE__ */ jsx("span", { children: fmt(domainMax) })
|
|
65
|
+
] })
|
|
66
|
+
]
|
|
67
|
+
}
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
export { RangeBar };
|
|
73
|
+
//# sourceMappingURL=chunk-5AVBKEDQ.js.map
|
|
74
|
+
//# sourceMappingURL=chunk-5AVBKEDQ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/range-bar/RangeBar.tsx"],"names":["RangeBar"],"mappings":"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","file":"chunk-5AVBKEDQ.js","sourcesContent":["import * as React from 'react'\nimport { cn } from '../../lib/utils'\n\nexport interface RangeBarProps extends React.ComponentProps<'div'> {\n low: number\n high: number\n min?: number\n max?: number\n value?: number | null\n unit?: string\n label?: string\n valueLabel?: string\n}\n\nfunction pct(value: number, domainMin: number, domainMax: number): number {\n if (domainMax === domainMin) return 0\n return ((value - domainMin) / (domainMax - domainMin)) * 100\n}\n\nfunction fmt(value: number): string {\n return Number.isInteger(value)\n ? value.toLocaleString()\n : value.toFixed(1).replace(/\\.0$/, '')\n}\n\nexport const RangeBar = React.forwardRef<HTMLDivElement, RangeBarProps>(\n function RangeBar(\n { low, high, min, max, value, unit, label, valueLabel = 'You', className, ...props },\n ref,\n ) {\n if (!Number.isFinite(low) || !Number.isFinite(high) || high <= low) {\n return null\n }\n\n const span = high - low\n let domainMin = min ?? low - span\n let domainMax = max ?? high + span\n if (domainMin < 0 && low >= 0) {\n const shift = -domainMin\n domainMin = 0\n domainMax += shift\n }\n if (domainMax <= domainMin) domainMax = domainMin + span\n\n const left = Math.max(0, Math.min(100, pct(low, domainMin, domainMax)))\n const right = Math.max(0, Math.min(100, pct(high, domainMin, domainMax)))\n const valuePct =\n value !== null && value !== undefined && Number.isFinite(value)\n ? Math.max(0, Math.min(100, pct(value, domainMin, domainMax)))\n : null\n\n return (\n <div\n ref={ref}\n data-as=\"range-bar\"\n className={cn('w-full', className)}\n {...props}\n >\n {label ? (\n <p className=\"mb-1 text-xs text-[var(--as-muted-fg)]\">{label}</p>\n ) : null}\n <div className=\"relative h-3.5 w-full rounded-full bg-[var(--as-muted)]\">\n <div\n className=\"absolute h-full rounded-full bg-[color-mix(in_srgb,var(--as-primary)_30%,transparent)]\"\n style={{ left: `${left}%`, width: `${Math.max(0, right - left)}%` }}\n title={`${label ? `${label}: ` : ''}${fmt(low)} – ${fmt(high)}${unit ? ` ${unit}` : ''}`}\n />\n {valuePct !== null ? (\n <div\n className=\"absolute top-1/2 size-2.5 -translate-x-1/2 -translate-y-1/2 rounded-full border-2 border-[var(--as-surface-raised)] bg-[var(--as-primary)] shadow-[var(--as-shadow-1)]\"\n style={{ left: `${valuePct}%` }}\n title={`${valueLabel}: ${fmt(value as number)}${unit ? ` ${unit}` : ''}`}\n />\n ) : null}\n </div>\n <div className=\"mt-0.5 flex justify-between text-[10px] text-[var(--as-muted-fg)]\">\n <span>{fmt(domainMin)}</span>\n <span className=\"font-medium\">\n {fmt(low)} – {fmt(high)}\n {unit ? ` ${unit}` : ''}\n </span>\n <span>{fmt(domainMax)}</span>\n </div>\n </div>\n )\n },\n)\n"]}
|
|
@@ -9,6 +9,7 @@ function FormModal({
|
|
|
9
9
|
title,
|
|
10
10
|
description,
|
|
11
11
|
icon: Icon,
|
|
12
|
+
headerActions,
|
|
12
13
|
children,
|
|
13
14
|
onSubmit,
|
|
14
15
|
submitting = false,
|
|
@@ -18,7 +19,11 @@ function FormModal({
|
|
|
18
19
|
closeLabel = "Close",
|
|
19
20
|
size = "md",
|
|
20
21
|
contentClassName,
|
|
21
|
-
|
|
22
|
+
bodyClassName,
|
|
23
|
+
footer,
|
|
24
|
+
hideFooter = false,
|
|
25
|
+
onReject,
|
|
26
|
+
rejectLabel = "Reject"
|
|
22
27
|
}) {
|
|
23
28
|
return /* @__PURE__ */ jsx(Modal, { open, onOpenChange, children: /* @__PURE__ */ jsx(ModalContent, { size, closeLabel, "aria-describedby": void 0, children: /* @__PURE__ */ jsxs(
|
|
24
29
|
"form",
|
|
@@ -35,12 +40,24 @@ function FormModal({
|
|
|
35
40
|
/* @__PURE__ */ jsxs(ModalHeader, { children: [
|
|
36
41
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
37
42
|
Icon ? /* @__PURE__ */ jsx("span", { className: "rounded-[var(--as-radius)] bg-[var(--as-secondary)] p-2 text-[var(--as-fg)]", children: /* @__PURE__ */ jsx(Icon, { "aria-hidden": "true", className: "size-5" }) }) : null,
|
|
38
|
-
/* @__PURE__ */ jsx(ModalTitle, { children: title })
|
|
43
|
+
/* @__PURE__ */ jsx(ModalTitle, { children: title }),
|
|
44
|
+
headerActions ? /* @__PURE__ */ jsx("span", { className: "ml-auto flex items-center gap-1.5", children: headerActions }) : null
|
|
39
45
|
] }),
|
|
40
46
|
description ? /* @__PURE__ */ jsx(ModalDescription, { children: description }) : null
|
|
41
47
|
] }),
|
|
42
|
-
/* @__PURE__ */ jsx("div", { className: "px-6 pb-2", children }),
|
|
43
|
-
footer ?? /* @__PURE__ */ jsxs(ModalFooter, { children: [
|
|
48
|
+
/* @__PURE__ */ jsx("div", { className: cn("px-6 pb-2", bodyClassName), children }),
|
|
49
|
+
footer ?? (hideFooter ? null : /* @__PURE__ */ jsxs(ModalFooter, { children: [
|
|
50
|
+
onReject ? /* @__PURE__ */ jsx(
|
|
51
|
+
Button,
|
|
52
|
+
{
|
|
53
|
+
type: "button",
|
|
54
|
+
variant: "destructive",
|
|
55
|
+
onClick: onReject,
|
|
56
|
+
disabled: submitting,
|
|
57
|
+
className: "sm:mr-auto",
|
|
58
|
+
children: rejectLabel
|
|
59
|
+
}
|
|
60
|
+
) : null,
|
|
44
61
|
/* @__PURE__ */ jsx(
|
|
45
62
|
Button,
|
|
46
63
|
{
|
|
@@ -52,12 +69,12 @@ function FormModal({
|
|
|
52
69
|
}
|
|
53
70
|
),
|
|
54
71
|
onSubmit ? /* @__PURE__ */ jsx(Button, { type: "submit", disabled: submitDisabled || submitting, loading: submitting, children: submitLabel }) : null
|
|
55
|
-
] })
|
|
72
|
+
] }))
|
|
56
73
|
]
|
|
57
74
|
}
|
|
58
75
|
) }) });
|
|
59
76
|
}
|
|
60
77
|
|
|
61
78
|
export { FormModal };
|
|
62
|
-
//# sourceMappingURL=chunk-
|
|
63
|
-
//# sourceMappingURL=chunk-
|
|
79
|
+
//# sourceMappingURL=chunk-5HXDKOBY.js.map
|
|
80
|
+
//# sourceMappingURL=chunk-5HXDKOBY.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/form-modal/FormModal.tsx"],"names":[],"mappings":"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","file":"chunk-5HXDKOBY.js","sourcesContent":["import * as React from 'react'\nimport type { LucideIcon } from 'lucide-react'\nimport { cn } from '../../lib/utils'\nimport { Button } from '../button/Button'\nimport {\n Modal,\n ModalContent,\n ModalDescription,\n ModalFooter,\n ModalHeader,\n ModalTitle,\n} from '../modal/Modal'\n\nexport interface FormModalProps {\n open: boolean\n onOpenChange: (open: boolean) => void\n title: React.ReactNode\n description?: React.ReactNode\n icon?: LucideIcon\n headerActions?: React.ReactNode\n children: React.ReactNode\n onSubmit?: () => void\n submitting?: boolean\n submitDisabled?: boolean\n submitLabel?: string\n cancelLabel?: string\n closeLabel?: string\n size?: 'sm' | 'md' | 'lg' | 'xl'\n contentClassName?: string\n bodyClassName?: string\n footer?: React.ReactNode\n hideFooter?: boolean\n onReject?: () => void\n rejectLabel?: string\n}\n\nexport function FormModal({\n open,\n onOpenChange,\n title,\n description,\n icon: Icon,\n headerActions,\n children,\n onSubmit,\n submitting = false,\n submitDisabled = false,\n submitLabel = 'Save',\n cancelLabel = 'Cancel',\n closeLabel = 'Close',\n size = 'md',\n contentClassName,\n bodyClassName,\n footer,\n hideFooter = false,\n onReject,\n rejectLabel = 'Reject',\n}: FormModalProps) {\n return (\n <Modal open={open} onOpenChange={onOpenChange}>\n <ModalContent size={size} closeLabel={closeLabel} aria-describedby={undefined}>\n <form\n data-as=\"form-modal\"\n className={cn('contents', contentClassName)}\n onSubmit={(event) => {\n event.preventDefault()\n if (!submitting && !submitDisabled) {\n onSubmit?.()\n }\n }}\n >\n <ModalHeader>\n <div className=\"flex items-center gap-3\">\n {Icon ? (\n <span className=\"rounded-[var(--as-radius)] bg-[var(--as-secondary)] p-2 text-[var(--as-fg)]\">\n <Icon aria-hidden=\"true\" className=\"size-5\" />\n </span>\n ) : null}\n <ModalTitle>{title}</ModalTitle>\n {headerActions ? (\n <span className=\"ml-auto flex items-center gap-1.5\">{headerActions}</span>\n ) : null}\n </div>\n {description ? <ModalDescription>{description}</ModalDescription> : null}\n </ModalHeader>\n <div className={cn('px-6 pb-2', bodyClassName)}>{children}</div>\n {footer ?? (hideFooter ? null : (\n <ModalFooter>\n {onReject ? (\n <Button\n type=\"button\"\n variant=\"destructive\"\n onClick={onReject}\n disabled={submitting}\n className=\"sm:mr-auto\"\n >\n {rejectLabel}\n </Button>\n ) : null}\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => onOpenChange(false)}\n disabled={submitting}\n >\n {cancelLabel}\n </Button>\n {onSubmit ? (\n <Button type=\"submit\" disabled={submitDisabled || submitting} loading={submitting}>\n {submitLabel}\n </Button>\n ) : null}\n </ModalFooter>\n ))}\n </form>\n </ModalContent>\n </Modal>\n )\n}\n"]}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { cn } from './chunk-BLJWR4ZV.js';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
4
|
+
|
|
5
|
+
var Table = React.forwardRef(
|
|
6
|
+
function Table2({ headers, rows, emptyText = "Nothing here yet", className, ...props }, ref) {
|
|
7
|
+
return /* @__PURE__ */ jsx(
|
|
8
|
+
"div",
|
|
9
|
+
{
|
|
10
|
+
ref,
|
|
11
|
+
"data-as": "table",
|
|
12
|
+
className: cn("overflow-x-auto", className),
|
|
13
|
+
...props,
|
|
14
|
+
children: /* @__PURE__ */ jsxs("table", { className: "min-w-full divide-y divide-[var(--as-border)]", children: [
|
|
15
|
+
/* @__PURE__ */ jsx("thead", { className: "bg-[var(--as-muted)]", children: /* @__PURE__ */ jsx("tr", { children: headers.map((header, index) => /* @__PURE__ */ jsx(
|
|
16
|
+
"th",
|
|
17
|
+
{
|
|
18
|
+
scope: "col",
|
|
19
|
+
className: "px-4 py-2.5 text-left text-xs font-medium uppercase tracking-wider text-[var(--as-muted-fg)]",
|
|
20
|
+
children: header
|
|
21
|
+
},
|
|
22
|
+
index
|
|
23
|
+
)) }) }),
|
|
24
|
+
/* @__PURE__ */ jsx("tbody", { className: "divide-y divide-[color-mix(in_srgb,var(--as-border)_55%,transparent)] bg-[var(--as-surface-raised)]", children: rows.length === 0 ? /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx(
|
|
25
|
+
"td",
|
|
26
|
+
{
|
|
27
|
+
colSpan: headers.length,
|
|
28
|
+
className: "px-4 py-6 text-center text-sm text-[var(--as-muted-fg)]",
|
|
29
|
+
children: emptyText
|
|
30
|
+
}
|
|
31
|
+
) }) : rows.map((row, rowIndex) => /* @__PURE__ */ jsx(
|
|
32
|
+
"tr",
|
|
33
|
+
{
|
|
34
|
+
className: "transition-colors hover:bg-[color-mix(in_srgb,var(--as-muted)_60%,transparent)]",
|
|
35
|
+
children: row.map((cell, cellIndex) => /* @__PURE__ */ jsx(
|
|
36
|
+
"td",
|
|
37
|
+
{
|
|
38
|
+
className: "whitespace-nowrap px-4 py-3 text-sm text-[var(--as-fg)]",
|
|
39
|
+
children: cell
|
|
40
|
+
},
|
|
41
|
+
cellIndex
|
|
42
|
+
))
|
|
43
|
+
},
|
|
44
|
+
rowIndex
|
|
45
|
+
)) })
|
|
46
|
+
] })
|
|
47
|
+
}
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
export { Table };
|
|
53
|
+
//# sourceMappingURL=chunk-5X3RYDPC.js.map
|
|
54
|
+
//# sourceMappingURL=chunk-5X3RYDPC.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/table/Table.tsx"],"names":["Table"],"mappings":";;;;AASO,IAAM,KAAA,GAAc,KAAA,CAAA,UAAA;AAAA,EACzB,SAASA,MAAAA,CAAM,EAAE,OAAA,EAAS,IAAA,EAAM,SAAA,GAAY,kBAAA,EAAoB,SAAA,EAAW,GAAG,KAAA,EAAM,EAAG,GAAA,EAAK;AAC1F,IAAA,uBACE,GAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,GAAA;AAAA,QACA,SAAA,EAAQ,OAAA;AAAA,QACR,SAAA,EAAW,EAAA,CAAG,iBAAA,EAAmB,SAAS,CAAA;AAAA,QACzC,GAAG,KAAA;AAAA,QAEJ,QAAA,kBAAA,IAAA,CAAC,OAAA,EAAA,EAAM,SAAA,EAAU,+CAAA,EACf,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,OAAA,EAAA,EAAM,WAAU,sBAAA,EACf,QAAA,kBAAA,GAAA,CAAC,QACE,QAAA,EAAA,OAAA,CAAQ,GAAA,CAAI,CAAC,MAAA,EAAQ,KAAA,qBACpB,GAAA;AAAA,YAAC,IAAA;AAAA,YAAA;AAAA,cAEC,KAAA,EAAM,KAAA;AAAA,cACN,SAAA,EAAU,8FAAA;AAAA,cAET,QAAA,EAAA;AAAA,aAAA;AAAA,YAJI;AAAA,WAMR,GACH,CAAA,EACF,CAAA;AAAA,0BACA,GAAA,CAAC,WAAM,SAAA,EAAU,qGAAA,EACd,eAAK,MAAA,KAAW,CAAA,uBACd,IAAA,EAAA,EACC,QAAA,kBAAA,GAAA;AAAA,YAAC,IAAA;AAAA,YAAA;AAAA,cACC,SAAS,OAAA,CAAQ,MAAA;AAAA,cACjB,SAAA,EAAU,yDAAA;AAAA,cAET,QAAA,EAAA;AAAA;AAAA,aAEL,CAAA,GAEA,IAAA,CAAK,GAAA,CAAI,CAAC,KAAK,QAAA,qBACb,GAAA;AAAA,YAAC,IAAA;AAAA,YAAA;AAAA,cAEC,SAAA,EAAU,iFAAA;AAAA,cAET,QAAA,EAAA,GAAA,CAAI,GAAA,CAAI,CAAC,IAAA,EAAM,SAAA,qBACd,GAAA;AAAA,gBAAC,IAAA;AAAA,gBAAA;AAAA,kBAEC,SAAA,EAAU,yDAAA;AAAA,kBAET,QAAA,EAAA;AAAA,iBAAA;AAAA,gBAHI;AAAA,eAKR;AAAA,aAAA;AAAA,YAVI;AAAA,WAYR,CAAA,EAEL;AAAA,SAAA,EACF;AAAA;AAAA,KACF;AAAA,EAEJ;AACF","file":"chunk-5X3RYDPC.js","sourcesContent":["import * as React from 'react'\nimport { cn } from '../../lib/utils'\n\nexport interface TableProps extends React.ComponentProps<'div'> {\n headers: string[]\n rows: React.ReactNode[][]\n emptyText?: string\n}\n\nexport const Table = React.forwardRef<HTMLDivElement, TableProps>(\n function Table({ headers, rows, emptyText = 'Nothing here yet', className, ...props }, ref) {\n return (\n <div\n ref={ref}\n data-as=\"table\"\n className={cn('overflow-x-auto', className)}\n {...props}\n >\n <table className=\"min-w-full divide-y divide-[var(--as-border)]\">\n <thead className=\"bg-[var(--as-muted)]\">\n <tr>\n {headers.map((header, index) => (\n <th\n key={index}\n scope=\"col\"\n className=\"px-4 py-2.5 text-left text-xs font-medium uppercase tracking-wider text-[var(--as-muted-fg)]\"\n >\n {header}\n </th>\n ))}\n </tr>\n </thead>\n <tbody className=\"divide-y divide-[color-mix(in_srgb,var(--as-border)_55%,transparent)] bg-[var(--as-surface-raised)]\">\n {rows.length === 0 ? (\n <tr>\n <td\n colSpan={headers.length}\n className=\"px-4 py-6 text-center text-sm text-[var(--as-muted-fg)]\"\n >\n {emptyText}\n </td>\n </tr>\n ) : (\n rows.map((row, rowIndex) => (\n <tr\n key={rowIndex}\n className=\"transition-colors hover:bg-[color-mix(in_srgb,var(--as-muted)_60%,transparent)]\"\n >\n {row.map((cell, cellIndex) => (\n <td\n key={cellIndex}\n className=\"whitespace-nowrap px-4 py-3 text-sm text-[var(--as-fg)]\"\n >\n {cell}\n </td>\n ))}\n </tr>\n ))\n )}\n </tbody>\n </table>\n </div>\n )\n },\n)\n"]}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { cn } from './chunk-BLJWR4ZV.js';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { Check, Copy } from 'lucide-react';
|
|
4
|
+
import { jsx } from 'react/jsx-runtime';
|
|
5
|
+
|
|
6
|
+
function writeClipboard(value) {
|
|
7
|
+
if (navigator?.clipboard?.writeText) {
|
|
8
|
+
return navigator.clipboard.writeText(value);
|
|
9
|
+
}
|
|
10
|
+
return new Promise((resolve, reject) => {
|
|
11
|
+
try {
|
|
12
|
+
const textarea = document.createElement("textarea");
|
|
13
|
+
textarea.value = value;
|
|
14
|
+
textarea.style.position = "fixed";
|
|
15
|
+
textarea.style.opacity = "0";
|
|
16
|
+
document.body.appendChild(textarea);
|
|
17
|
+
textarea.select();
|
|
18
|
+
document.execCommand("copy");
|
|
19
|
+
document.body.removeChild(textarea);
|
|
20
|
+
resolve();
|
|
21
|
+
} catch (error) {
|
|
22
|
+
reject(error);
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
var CopyButton = React.forwardRef(
|
|
27
|
+
function CopyButton2({
|
|
28
|
+
value,
|
|
29
|
+
label = "Copy",
|
|
30
|
+
size = 14,
|
|
31
|
+
hideWhenEmpty = true,
|
|
32
|
+
copiedDuration = 1500,
|
|
33
|
+
onCopied,
|
|
34
|
+
onCopyError,
|
|
35
|
+
className,
|
|
36
|
+
onClick,
|
|
37
|
+
...props
|
|
38
|
+
}, ref) {
|
|
39
|
+
const [copied, setCopied] = React.useState(false);
|
|
40
|
+
const timer = React.useRef(null);
|
|
41
|
+
React.useEffect(
|
|
42
|
+
() => () => {
|
|
43
|
+
if (timer.current) clearTimeout(timer.current);
|
|
44
|
+
},
|
|
45
|
+
[]
|
|
46
|
+
);
|
|
47
|
+
if (hideWhenEmpty && !value) return null;
|
|
48
|
+
const Icon = copied ? Check : Copy;
|
|
49
|
+
return /* @__PURE__ */ jsx(
|
|
50
|
+
"button",
|
|
51
|
+
{
|
|
52
|
+
ref,
|
|
53
|
+
type: "button",
|
|
54
|
+
"data-as": "copy-button",
|
|
55
|
+
"data-copied": copied || void 0,
|
|
56
|
+
"aria-label": label,
|
|
57
|
+
title: label,
|
|
58
|
+
onClick: (event) => {
|
|
59
|
+
onClick?.(event);
|
|
60
|
+
if (event.defaultPrevented || !value) return;
|
|
61
|
+
event.preventDefault();
|
|
62
|
+
event.stopPropagation();
|
|
63
|
+
writeClipboard(value).then(
|
|
64
|
+
() => {
|
|
65
|
+
setCopied(true);
|
|
66
|
+
if (timer.current) clearTimeout(timer.current);
|
|
67
|
+
timer.current = setTimeout(() => setCopied(false), copiedDuration);
|
|
68
|
+
onCopied?.();
|
|
69
|
+
},
|
|
70
|
+
(error) => {
|
|
71
|
+
onCopyError?.(error);
|
|
72
|
+
}
|
|
73
|
+
);
|
|
74
|
+
},
|
|
75
|
+
className: cn(
|
|
76
|
+
"inline-flex cursor-pointer items-center justify-center rounded-[var(--as-radius-sm)] p-0.5 text-[var(--as-muted-fg)] transition-colors hover:text-[var(--as-primary)] focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)]",
|
|
77
|
+
copied && "text-[var(--as-success)] hover:text-[var(--as-success)]",
|
|
78
|
+
className
|
|
79
|
+
),
|
|
80
|
+
...props,
|
|
81
|
+
children: /* @__PURE__ */ jsx(Icon, { style: { width: size, height: size }, "aria-hidden": true })
|
|
82
|
+
}
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
export { CopyButton };
|
|
88
|
+
//# sourceMappingURL=chunk-CZ2BL2ZL.js.map
|
|
89
|
+
//# sourceMappingURL=chunk-CZ2BL2ZL.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/copy-button/CopyButton.tsx"],"names":["CopyButton"],"mappings":"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","file":"chunk-CZ2BL2ZL.js","sourcesContent":["import * as React from 'react'\nimport { Check, Copy } from 'lucide-react'\nimport { cn } from '../../lib/utils'\n\nexport interface CopyButtonProps\n extends Omit<React.ComponentProps<'button'>, 'value' | 'children'> {\n value: string\n label?: string\n size?: number\n hideWhenEmpty?: boolean\n copiedDuration?: number\n onCopied?: () => void\n onCopyError?: (error: unknown) => void\n}\n\nfunction writeClipboard(value: string): Promise<void> {\n if (navigator?.clipboard?.writeText) {\n return navigator.clipboard.writeText(value)\n }\n return new Promise((resolve, reject) => {\n try {\n const textarea = document.createElement('textarea')\n textarea.value = value\n textarea.style.position = 'fixed'\n textarea.style.opacity = '0'\n document.body.appendChild(textarea)\n textarea.select()\n document.execCommand('copy')\n document.body.removeChild(textarea)\n resolve()\n } catch (error) {\n reject(error)\n }\n })\n}\n\nexport const CopyButton = React.forwardRef<HTMLButtonElement, CopyButtonProps>(\n function CopyButton(\n {\n value,\n label = 'Copy',\n size = 14,\n hideWhenEmpty = true,\n copiedDuration = 1500,\n onCopied,\n onCopyError,\n className,\n onClick,\n ...props\n },\n ref,\n ) {\n const [copied, setCopied] = React.useState(false)\n const timer = React.useRef<ReturnType<typeof setTimeout> | null>(null)\n\n React.useEffect(\n () => () => {\n if (timer.current) clearTimeout(timer.current)\n },\n [],\n )\n\n if (hideWhenEmpty && !value) return null\n\n const Icon = copied ? Check : Copy\n\n return (\n <button\n ref={ref}\n type=\"button\"\n data-as=\"copy-button\"\n data-copied={copied || undefined}\n aria-label={label}\n title={label}\n onClick={(event) => {\n onClick?.(event)\n if (event.defaultPrevented || !value) return\n event.preventDefault()\n event.stopPropagation()\n writeClipboard(value).then(\n () => {\n setCopied(true)\n if (timer.current) clearTimeout(timer.current)\n timer.current = setTimeout(() => setCopied(false), copiedDuration)\n onCopied?.()\n },\n (error) => {\n onCopyError?.(error)\n },\n )\n }}\n className={cn(\n 'inline-flex cursor-pointer items-center justify-center rounded-[var(--as-radius-sm)] p-0.5 text-[var(--as-muted-fg)] transition-colors hover:text-[var(--as-primary)] focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)]',\n copied && 'text-[var(--as-success)] hover:text-[var(--as-success)]',\n className,\n )}\n {...props}\n >\n <Icon style={{ width: size, height: size }} aria-hidden />\n </button>\n )\n },\n)\n"]}
|