@inshorts/glint-ui 0.5.4 → 0.6.1
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 +3 -1
- package/dist/alert.cjs +96 -0
- package/dist/alert.cjs.map +1 -0
- package/dist/alert.d.cts +29 -0
- package/dist/alert.d.ts +29 -0
- package/dist/alert.js +10 -0
- package/dist/alert.js.map +1 -0
- package/dist/autocomplete.cjs +578 -0
- package/dist/autocomplete.cjs.map +1 -0
- package/dist/autocomplete.d.cts +56 -0
- package/dist/autocomplete.d.ts +56 -0
- package/dist/autocomplete.js +11 -0
- package/dist/autocomplete.js.map +1 -0
- package/dist/badge.cjs +89 -0
- package/dist/badge.cjs.map +1 -0
- package/dist/badge.d.cts +25 -0
- package/dist/badge.d.ts +25 -0
- package/dist/badge.js +10 -0
- package/dist/badge.js.map +1 -0
- package/dist/breadcrumb.cjs +88 -0
- package/dist/breadcrumb.cjs.map +1 -0
- package/dist/breadcrumb.d.cts +14 -0
- package/dist/breadcrumb.d.ts +14 -0
- package/dist/breadcrumb.js +8 -0
- package/dist/breadcrumb.js.map +1 -0
- package/dist/button.cjs +143 -0
- package/dist/button.cjs.map +1 -0
- package/dist/button.d.cts +34 -0
- package/dist/button.d.ts +34 -0
- package/dist/button.js +9 -0
- package/dist/button.js.map +1 -0
- package/dist/card.cjs +111 -0
- package/dist/card.cjs.map +1 -0
- package/dist/card.d.cts +15 -0
- package/dist/card.d.ts +15 -0
- package/dist/card.js +18 -0
- package/dist/card.js.map +1 -0
- package/dist/checkbox.cjs +66 -0
- package/dist/checkbox.cjs.map +1 -0
- package/{src/checkbox.tsx → dist/checkbox.d.cts} +5 -22
- package/dist/checkbox.d.ts +25 -0
- package/dist/checkbox.js +10 -0
- package/dist/checkbox.js.map +1 -0
- package/dist/chunk-5MEOZHJA.js +513 -0
- package/dist/chunk-5MEOZHJA.js.map +1 -0
- package/dist/chunk-67ACNS42.js +29 -0
- package/dist/chunk-67ACNS42.js.map +1 -0
- package/dist/chunk-A6GRLKOO.js +85 -0
- package/dist/chunk-A6GRLKOO.js.map +1 -0
- package/dist/chunk-DS3QYIKL.js +90 -0
- package/dist/chunk-DS3QYIKL.js.map +1 -0
- package/dist/chunk-EWSBFU54.js +53 -0
- package/dist/chunk-EWSBFU54.js.map +1 -0
- package/dist/chunk-G4ZQUSAJ.js +38 -0
- package/dist/chunk-G4ZQUSAJ.js.map +1 -0
- package/dist/chunk-GMCUXEFI.js +67 -0
- package/dist/chunk-GMCUXEFI.js.map +1 -0
- package/dist/chunk-HBBOR43A.js +85 -0
- package/dist/chunk-HBBOR43A.js.map +1 -0
- package/dist/chunk-HCA5ODCD.js +11 -0
- package/dist/chunk-HCA5ODCD.js.map +1 -0
- package/dist/chunk-HYRJYUPI.js +26 -0
- package/dist/chunk-HYRJYUPI.js.map +1 -0
- package/dist/chunk-IRCTGJQB.js +26 -0
- package/dist/chunk-IRCTGJQB.js.map +1 -0
- package/dist/chunk-ISPICB4W.js +70 -0
- package/dist/chunk-ISPICB4W.js.map +1 -0
- package/dist/chunk-JDE5XYPT.js +30 -0
- package/dist/chunk-JDE5XYPT.js.map +1 -0
- package/dist/chunk-JSJEEKR3.js +59 -0
- package/dist/chunk-JSJEEKR3.js.map +1 -0
- package/dist/chunk-KR3BCFP7.js +85 -0
- package/dist/chunk-KR3BCFP7.js.map +1 -0
- package/dist/chunk-MLRSOTFI.js +81 -0
- package/dist/chunk-MLRSOTFI.js.map +1 -0
- package/dist/chunk-MQT5RAQV.js +202 -0
- package/dist/chunk-MQT5RAQV.js.map +1 -0
- package/dist/chunk-MUPW2TFJ.js +102 -0
- package/dist/chunk-MUPW2TFJ.js.map +1 -0
- package/dist/chunk-OUYT6SPU.js +76 -0
- package/dist/chunk-OUYT6SPU.js.map +1 -0
- package/dist/chunk-PM2VE7DJ.js +100 -0
- package/dist/chunk-PM2VE7DJ.js.map +1 -0
- package/dist/chunk-PPYR3O3L.js +44 -0
- package/dist/chunk-PPYR3O3L.js.map +1 -0
- package/dist/chunk-PUTC52SI.js +98 -0
- package/dist/chunk-PUTC52SI.js.map +1 -0
- package/dist/chunk-PWAKTEXF.js +18 -0
- package/dist/chunk-PWAKTEXF.js.map +1 -0
- package/dist/chunk-QTFWORA7.js +26 -0
- package/dist/chunk-QTFWORA7.js.map +1 -0
- package/dist/chunk-RUPL2H6V.js +49 -0
- package/dist/chunk-RUPL2H6V.js.map +1 -0
- package/dist/chunk-S7PVZAPL.js +28 -0
- package/dist/chunk-S7PVZAPL.js.map +1 -0
- package/dist/chunk-SQDV2AKJ.js +49 -0
- package/dist/chunk-SQDV2AKJ.js.map +1 -0
- package/dist/chunk-T2KXVH3O.js +297 -0
- package/dist/chunk-T2KXVH3O.js.map +1 -0
- package/dist/chunk-T4WCCHJQ.js +29 -0
- package/dist/chunk-T4WCCHJQ.js.map +1 -0
- package/dist/chunk-UC3ZIQPE.js +93 -0
- package/dist/chunk-UC3ZIQPE.js.map +1 -0
- package/dist/chunk-UE7JY7VR.js +28 -0
- package/dist/chunk-UE7JY7VR.js.map +1 -0
- package/dist/chunk-Y5WCT6XN.js +93 -0
- package/dist/chunk-Y5WCT6XN.js.map +1 -0
- package/dist/chunk-YDICVETX.js +151 -0
- package/dist/chunk-YDICVETX.js.map +1 -0
- package/dist/chunk-ZFSQVMLJ.js +126 -0
- package/dist/chunk-ZFSQVMLJ.js.map +1 -0
- package/dist/chunk-ZHATD73Y.js +46 -0
- package/dist/chunk-ZHATD73Y.js.map +1 -0
- package/dist/chunk-ZLAA4DGG.js +111 -0
- package/dist/chunk-ZLAA4DGG.js.map +1 -0
- package/dist/chunk-ZP252OJZ.js +56 -0
- package/dist/chunk-ZP252OJZ.js.map +1 -0
- package/dist/clipboard.cjs +125 -0
- package/dist/clipboard.cjs.map +1 -0
- package/dist/clipboard.d.cts +52 -0
- package/dist/clipboard.d.ts +52 -0
- package/dist/clipboard.js +23 -0
- package/dist/clipboard.js.map +1 -0
- package/dist/collapsible.cjs +94 -0
- package/dist/collapsible.cjs.map +1 -0
- package/dist/collapsible.d.cts +21 -0
- package/dist/collapsible.d.ts +21 -0
- package/dist/collapsible.js +9 -0
- package/dist/collapsible.js.map +1 -0
- package/dist/confirm-dialog.cjs +369 -0
- package/dist/confirm-dialog.cjs.map +1 -0
- package/dist/confirm-dialog.d.cts +16 -0
- package/dist/confirm-dialog.d.ts +16 -0
- package/dist/confirm-dialog.js +13 -0
- package/dist/confirm-dialog.js.map +1 -0
- package/dist/copy-button.cjs +102 -0
- package/dist/copy-button.cjs.map +1 -0
- package/dist/copy-button.d.cts +18 -0
- package/dist/copy-button.d.ts +18 -0
- package/dist/copy-button.js +10 -0
- package/dist/copy-button.js.map +1 -0
- package/dist/data-table.cjs +140 -0
- package/dist/data-table.cjs.map +1 -0
- package/dist/data-table.d.cts +81 -0
- package/dist/data-table.d.ts +81 -0
- package/dist/data-table.js +8 -0
- package/dist/data-table.js.map +1 -0
- package/dist/date-range-picker/dateRange.cjs +138 -0
- package/dist/date-range-picker/dateRange.cjs.map +1 -0
- package/dist/date-range-picker/dateRange.d.cts +57 -0
- package/dist/date-range-picker/dateRange.d.ts +57 -0
- package/dist/date-range-picker/dateRange.js +31 -0
- package/dist/date-range-picker/dateRange.js.map +1 -0
- package/dist/date-range-picker/index.cjs +375 -0
- package/dist/date-range-picker/index.cjs.map +1 -0
- package/dist/date-range-picker/index.d.cts +18 -0
- package/dist/date-range-picker/index.d.ts +18 -0
- package/dist/date-range-picker/index.js +10 -0
- package/dist/date-range-picker/index.js.map +1 -0
- package/dist/dialogLayer.cjs +121 -0
- package/dist/dialogLayer.cjs.map +1 -0
- package/dist/dialogLayer.d.cts +11 -0
- package/dist/dialogLayer.d.ts +11 -0
- package/dist/dialogLayer.js +8 -0
- package/dist/dialogLayer.js.map +1 -0
- package/dist/feature-access-gate.cjs +160 -0
- package/dist/feature-access-gate.cjs.map +1 -0
- package/dist/feature-access-gate.d.cts +14 -0
- package/dist/feature-access-gate.d.ts +14 -0
- package/dist/feature-access-gate.js +11 -0
- package/dist/feature-access-gate.js.map +1 -0
- package/dist/field.cjs +58 -0
- package/dist/field.cjs.map +1 -0
- package/dist/field.d.cts +23 -0
- package/dist/field.d.ts +23 -0
- package/dist/field.js +8 -0
- package/dist/field.js.map +1 -0
- package/dist/image-uploader.cjs +293 -0
- package/dist/image-uploader.cjs.map +1 -0
- package/dist/image-uploader.d.cts +34 -0
- package/dist/image-uploader.d.ts +34 -0
- package/dist/image-uploader.js +12 -0
- package/dist/image-uploader.js.map +1 -0
- package/dist/index.cjs +3008 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +41 -0
- package/dist/index.d.ts +41 -0
- package/dist/index.js +232 -0
- package/dist/index.js.map +1 -0
- package/dist/input.cjs +58 -0
- package/dist/input.cjs.map +1 -0
- package/dist/input.d.cts +7 -0
- package/dist/input.d.ts +7 -0
- package/dist/input.js +10 -0
- package/dist/input.js.map +1 -0
- package/dist/label.cjs +67 -0
- package/dist/label.cjs.map +1 -0
- package/dist/label.d.cts +7 -0
- package/dist/label.d.ts +7 -0
- package/dist/label.js +9 -0
- package/dist/label.js.map +1 -0
- package/dist/modal.cjs +212 -0
- package/dist/modal.cjs.map +1 -0
- package/dist/modal.d.cts +39 -0
- package/dist/modal.d.ts +39 -0
- package/dist/modal.js +12 -0
- package/dist/modal.js.map +1 -0
- package/dist/page-header.cjs +78 -0
- package/dist/page-header.cjs.map +1 -0
- package/dist/page-header.d.cts +35 -0
- package/dist/page-header.d.ts +35 -0
- package/dist/page-header.js +8 -0
- package/dist/page-header.js.map +1 -0
- package/dist/pagination.cjs +237 -0
- package/dist/pagination.cjs.map +1 -0
- package/dist/pagination.d.cts +15 -0
- package/dist/pagination.d.ts +15 -0
- package/dist/pagination.js +11 -0
- package/dist/pagination.js.map +1 -0
- package/dist/panel-brand-mark.cjs +59 -0
- package/dist/panel-brand-mark.cjs.map +1 -0
- package/dist/panel-brand-mark.d.cts +13 -0
- package/dist/panel-brand-mark.d.ts +13 -0
- package/dist/panel-brand-mark.js +8 -0
- package/dist/panel-brand-mark.js.map +1 -0
- package/dist/panel-sign-in.cjs +256 -0
- package/dist/panel-sign-in.cjs.map +1 -0
- package/dist/panel-sign-in.d.cts +31 -0
- package/dist/panel-sign-in.d.ts +31 -0
- package/dist/panel-sign-in.js +14 -0
- package/dist/panel-sign-in.js.map +1 -0
- package/dist/segmented-control.cjs +122 -0
- package/dist/segmented-control.cjs.map +1 -0
- package/dist/segmented-control.d.cts +58 -0
- package/dist/segmented-control.d.ts +58 -0
- package/dist/segmented-control.js +9 -0
- package/dist/segmented-control.js.map +1 -0
- package/dist/select.cjs +648 -0
- package/dist/select.cjs.map +1 -0
- package/dist/select.d.cts +30 -0
- package/dist/select.d.ts +30 -0
- package/dist/select.js +12 -0
- package/dist/select.js.map +1 -0
- package/dist/separator.cjs +70 -0
- package/dist/separator.cjs.map +1 -0
- package/dist/separator.d.cts +13 -0
- package/dist/separator.d.ts +13 -0
- package/dist/separator.js +9 -0
- package/dist/separator.js.map +1 -0
- package/dist/side-drawer.cjs +321 -0
- package/dist/side-drawer.cjs.map +1 -0
- package/dist/side-drawer.d.cts +21 -0
- package/dist/side-drawer.d.ts +21 -0
- package/dist/side-drawer.js +13 -0
- package/dist/side-drawer.js.map +1 -0
- package/dist/spinner.cjs +57 -0
- package/dist/spinner.cjs.map +1 -0
- package/{src/spinner.tsx → dist/spinner.d.cts} +11 -22
- package/dist/spinner.d.ts +27 -0
- package/dist/spinner.js +8 -0
- package/dist/spinner.js.map +1 -0
- package/dist/spreadsheet-grid.cjs +238 -0
- package/dist/spreadsheet-grid.cjs.map +1 -0
- package/dist/spreadsheet-grid.d.cts +48 -0
- package/dist/spreadsheet-grid.d.ts +48 -0
- package/dist/spreadsheet-grid.js +8 -0
- package/dist/spreadsheet-grid.js.map +1 -0
- package/dist/state-panel.cjs +86 -0
- package/dist/state-panel.cjs.map +1 -0
- package/dist/state-panel.d.cts +23 -0
- package/dist/state-panel.d.ts +23 -0
- package/dist/state-panel.js +9 -0
- package/dist/state-panel.js.map +1 -0
- package/dist/switch.cjs +87 -0
- package/dist/switch.cjs.map +1 -0
- package/dist/switch.d.cts +13 -0
- package/dist/switch.d.ts +13 -0
- package/dist/switch.js +9 -0
- package/dist/switch.js.map +1 -0
- package/dist/table.cjs +139 -0
- package/dist/table.cjs.map +1 -0
- package/dist/table.d.cts +16 -0
- package/dist/table.d.ts +16 -0
- package/dist/table.js +22 -0
- package/dist/table.js.map +1 -0
- package/dist/tabs.cjs +168 -0
- package/dist/tabs.cjs.map +1 -0
- package/dist/tabs.d.cts +59 -0
- package/dist/tabs.d.ts +59 -0
- package/dist/tabs.js +11 -0
- package/dist/tabs.js.map +1 -0
- package/dist/textarea.cjs +66 -0
- package/dist/textarea.cjs.map +1 -0
- package/dist/textarea.d.cts +18 -0
- package/dist/textarea.d.ts +18 -0
- package/dist/textarea.js +10 -0
- package/dist/textarea.js.map +1 -0
- package/dist/utils.cjs +35 -0
- package/dist/utils.cjs.map +1 -0
- package/dist/utils.d.cts +5 -0
- package/dist/utils.d.ts +5 -0
- package/dist/utils.js +7 -0
- package/dist/utils.js.map +1 -0
- package/package.json +391 -14
- package/src/alert.tsx +0 -74
- package/src/autocomplete.tsx +0 -666
- package/src/badge.tsx +0 -60
- package/src/breadcrumb.tsx +0 -71
- package/src/button.tsx +0 -113
- package/src/card.tsx +0 -79
- package/src/clipboard.ts +0 -144
- package/src/collapsible.tsx +0 -63
- package/src/confirm-dialog.tsx +0 -84
- package/src/copy-button.tsx +0 -58
- package/src/data-table.tsx +0 -190
- package/src/date-range-picker/dateRange.ts +0 -142
- package/src/date-range-picker/index.tsx +0 -366
- package/src/dialogLayer.ts +0 -142
- package/src/feature-access-gate.tsx +0 -38
- package/src/field.tsx +0 -56
- package/src/image-uploader.tsx +0 -181
- package/src/index.ts +0 -37
- package/src/input.tsx +0 -16
- package/src/label.tsx +0 -23
- package/src/modal.tsx +0 -117
- package/src/page-header.tsx +0 -75
- package/src/pagination.tsx +0 -116
- package/src/panel-brand-mark.tsx +0 -32
- package/src/panel-sign-in.tsx +0 -134
- package/src/segmented-control.tsx +0 -155
- package/src/select.tsx +0 -105
- package/src/separator.tsx +0 -32
- package/src/side-drawer.tsx +0 -87
- package/src/spreadsheet-grid.tsx +0 -264
- package/src/state-panel.tsx +0 -46
- package/src/switch.tsx +0 -47
- package/src/table.tsx +0 -110
- package/src/tabs.tsx +0 -201
- package/src/textarea.tsx +0 -32
- package/src/utils.ts +0 -6
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Autocomplete
|
|
3
|
+
} from "./chunk-5MEOZHJA.js";
|
|
4
|
+
|
|
5
|
+
// src/select.tsx
|
|
6
|
+
import * as React from "react";
|
|
7
|
+
import { jsx } from "react/jsx-runtime";
|
|
8
|
+
function optionText(node) {
|
|
9
|
+
if (node == null || typeof node === "boolean") return "";
|
|
10
|
+
if (typeof node === "string" || typeof node === "number") return String(node);
|
|
11
|
+
if (Array.isArray(node)) return node.map(optionText).join("");
|
|
12
|
+
if (React.isValidElement(node)) {
|
|
13
|
+
return optionText(node.props.children);
|
|
14
|
+
}
|
|
15
|
+
return "";
|
|
16
|
+
}
|
|
17
|
+
function optionsFromChildren(children) {
|
|
18
|
+
const options = [];
|
|
19
|
+
React.Children.forEach(children, (child) => {
|
|
20
|
+
if (!React.isValidElement(child)) return;
|
|
21
|
+
if (child.type === React.Fragment) {
|
|
22
|
+
options.push(
|
|
23
|
+
...optionsFromChildren(
|
|
24
|
+
child.props.children
|
|
25
|
+
)
|
|
26
|
+
);
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const props = child.props;
|
|
30
|
+
const value = props.value == null ? "" : String(props.value);
|
|
31
|
+
options.push({
|
|
32
|
+
value,
|
|
33
|
+
label: optionText(props.children).trim() || value,
|
|
34
|
+
disabled: Boolean(props.disabled)
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
return options;
|
|
38
|
+
}
|
|
39
|
+
function Select({
|
|
40
|
+
id,
|
|
41
|
+
className,
|
|
42
|
+
disabled,
|
|
43
|
+
value,
|
|
44
|
+
placeholder,
|
|
45
|
+
children,
|
|
46
|
+
onChange,
|
|
47
|
+
size = "default",
|
|
48
|
+
"aria-label": ariaLabel
|
|
49
|
+
}) {
|
|
50
|
+
const options = optionsFromChildren(children);
|
|
51
|
+
const current = Array.isArray(value) ? String(value[0] ?? "") : value == null ? "" : String(value);
|
|
52
|
+
const blank = options.find((option) => option.value === "");
|
|
53
|
+
return /* @__PURE__ */ jsx(
|
|
54
|
+
Autocomplete,
|
|
55
|
+
{
|
|
56
|
+
id,
|
|
57
|
+
className,
|
|
58
|
+
disabled: Boolean(disabled),
|
|
59
|
+
ariaLabel,
|
|
60
|
+
size,
|
|
61
|
+
options,
|
|
62
|
+
value: current,
|
|
63
|
+
clearable: false,
|
|
64
|
+
placeholder: placeholder ?? blank?.label ?? "Search\u2026",
|
|
65
|
+
onChange: (next) => onChange?.({
|
|
66
|
+
target: { value: next },
|
|
67
|
+
currentTarget: { value: next }
|
|
68
|
+
})
|
|
69
|
+
}
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export {
|
|
74
|
+
Select
|
|
75
|
+
};
|
|
76
|
+
//# sourceMappingURL=chunk-OUYT6SPU.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/select.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\n\nimport { Autocomplete, type AutocompleteOption } from \"./autocomplete\";\n\ntype SelectChange = {\n target: { value: string };\n currentTarget: { value: string };\n};\n\nexport type SelectProps = {\n id?: string;\n className?: string;\n disabled?: boolean;\n /** Accessible name when the control is not wrapped in a label. */\n \"aria-label\"?: string;\n /** `compact` fits a spreadsheet cell. Typing still filters the list. */\n size?: \"default\" | \"compact\";\n value?: string | number | readonly string[];\n placeholder?: string;\n children?: React.ReactNode;\n onChange?: (event: SelectChange) => void;\n};\n\nfunction optionText(node: React.ReactNode): string {\n if (node == null || typeof node === \"boolean\") return \"\";\n if (typeof node === \"string\" || typeof node === \"number\") return String(node);\n if (Array.isArray(node)) return node.map(optionText).join(\"\");\n if (React.isValidElement<{ children?: React.ReactNode }>(node)) {\n return optionText(node.props.children);\n }\n return \"\";\n}\n\nfunction optionsFromChildren(children: React.ReactNode): AutocompleteOption[] {\n const options: AutocompleteOption[] = [];\n React.Children.forEach(children, (child) => {\n if (!React.isValidElement(child)) return;\n if (child.type === React.Fragment) {\n options.push(\n ...optionsFromChildren(\n (child.props as { children?: React.ReactNode }).children,\n ),\n );\n return;\n }\n const props = child.props as {\n value?: string | number;\n disabled?: boolean;\n children?: React.ReactNode;\n };\n const value = props.value == null ? \"\" : String(props.value);\n options.push({\n value,\n label: optionText(props.children).trim() || value,\n disabled: Boolean(props.disabled),\n });\n });\n return options;\n}\n\n/**\n * The dropdown. It is the searchable autocomplete, not a native `<select>`,\n * so a long list can be typed into and an empty list still opens.\n */\nexport function Select({\n id,\n className,\n disabled,\n value,\n placeholder,\n children,\n onChange,\n size = \"default\",\n \"aria-label\": ariaLabel,\n}: SelectProps) {\n const options = optionsFromChildren(children);\n const current = Array.isArray(value)\n ? String(value[0] ?? \"\")\n : value == null\n ? \"\"\n : String(value);\n const blank = options.find((option) => option.value === \"\");\n\n return (\n <Autocomplete\n id={id}\n className={className}\n disabled={Boolean(disabled)}\n ariaLabel={ariaLabel}\n size={size}\n options={options}\n value={current}\n clearable={false}\n placeholder={placeholder ?? blank?.label ?? \"Search…\"}\n onChange={(next) =>\n onChange?.({\n target: { value: next },\n currentTarget: { value: next },\n })\n }\n />\n );\n}\n"],"mappings":";;;;;AAEA,YAAY,WAAW;AAoFnB;AA7DJ,SAAS,WAAW,MAA+B;AACjD,MAAI,QAAQ,QAAQ,OAAO,SAAS,UAAW,QAAO;AACtD,MAAI,OAAO,SAAS,YAAY,OAAO,SAAS,SAAU,QAAO,OAAO,IAAI;AAC5E,MAAI,MAAM,QAAQ,IAAI,EAAG,QAAO,KAAK,IAAI,UAAU,EAAE,KAAK,EAAE;AAC5D,MAAU,qBAA+C,IAAI,GAAG;AAC9D,WAAO,WAAW,KAAK,MAAM,QAAQ;AAAA,EACvC;AACA,SAAO;AACT;AAEA,SAAS,oBAAoB,UAAiD;AAC5E,QAAM,UAAgC,CAAC;AACvC,EAAM,eAAS,QAAQ,UAAU,CAAC,UAAU;AAC1C,QAAI,CAAO,qBAAe,KAAK,EAAG;AAClC,QAAI,MAAM,SAAe,gBAAU;AACjC,cAAQ;AAAA,QACN,GAAG;AAAA,UACA,MAAM,MAAyC;AAAA,QAClD;AAAA,MACF;AACA;AAAA,IACF;AACA,UAAM,QAAQ,MAAM;AAKpB,UAAM,QAAQ,MAAM,SAAS,OAAO,KAAK,OAAO,MAAM,KAAK;AAC3D,YAAQ,KAAK;AAAA,MACX;AAAA,MACA,OAAO,WAAW,MAAM,QAAQ,EAAE,KAAK,KAAK;AAAA,MAC5C,UAAU,QAAQ,MAAM,QAAQ;AAAA,IAClC,CAAC;AAAA,EACH,CAAC;AACD,SAAO;AACT;AAMO,SAAS,OAAO;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP,cAAc;AAChB,GAAgB;AACd,QAAM,UAAU,oBAAoB,QAAQ;AAC5C,QAAM,UAAU,MAAM,QAAQ,KAAK,IAC/B,OAAO,MAAM,CAAC,KAAK,EAAE,IACrB,SAAS,OACP,KACA,OAAO,KAAK;AAClB,QAAM,QAAQ,QAAQ,KAAK,CAAC,WAAW,OAAO,UAAU,EAAE;AAE1D,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA,UAAU,QAAQ,QAAQ;AAAA,MAC1B;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO;AAAA,MACP,WAAW;AAAA,MACX,aAAa,eAAe,OAAO,SAAS;AAAA,MAC5C,UAAU,CAAC,SACT,WAAW;AAAA,QACT,QAAQ,EAAE,OAAO,KAAK;AAAA,QACtB,eAAe,EAAE,OAAO,KAAK;AAAA,MAC/B,CAAC;AAAA;AAAA,EAEL;AAEJ;","names":[]}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import {
|
|
2
|
+
PanelBrandMark
|
|
3
|
+
} from "./chunk-JDE5XYPT.js";
|
|
4
|
+
import {
|
|
5
|
+
Button
|
|
6
|
+
} from "./chunk-KR3BCFP7.js";
|
|
7
|
+
import {
|
|
8
|
+
cn
|
|
9
|
+
} from "./chunk-HCA5ODCD.js";
|
|
10
|
+
|
|
11
|
+
// src/panel-sign-in.tsx
|
|
12
|
+
import { Loader2 } from "lucide-react";
|
|
13
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
14
|
+
function PanelSignIn({
|
|
15
|
+
appName,
|
|
16
|
+
eyebrow = "Secure Google sign-in",
|
|
17
|
+
description = "Use your work Google account to continue.",
|
|
18
|
+
features,
|
|
19
|
+
brandIcon,
|
|
20
|
+
error,
|
|
21
|
+
refused = false,
|
|
22
|
+
refusedTitle = "Access denied",
|
|
23
|
+
refusedMessage = "This Google account is signed in, but it is not provisioned for this panel.",
|
|
24
|
+
isSessionLoading = false,
|
|
25
|
+
isSigningIn = false,
|
|
26
|
+
onSignIn,
|
|
27
|
+
signInLabel = "Continue with Google",
|
|
28
|
+
className
|
|
29
|
+
}) {
|
|
30
|
+
const busy = isSessionLoading || isSigningIn;
|
|
31
|
+
return /* @__PURE__ */ jsx(
|
|
32
|
+
"main",
|
|
33
|
+
{
|
|
34
|
+
className: cn(
|
|
35
|
+
"bg-background text-foreground grid min-h-screen place-items-center p-4 sm:p-8",
|
|
36
|
+
className
|
|
37
|
+
),
|
|
38
|
+
children: /* @__PURE__ */ jsxs("section", { className: "border-border bg-card w-full max-w-md space-y-6 rounded-lg border p-8 shadow-sm", children: [
|
|
39
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
40
|
+
/* @__PURE__ */ jsx(PanelBrandMark, { children: brandIcon ?? /* @__PURE__ */ jsx("span", { className: "text-sm font-semibold", "aria-hidden": true, children: appName.slice(0, 1).toUpperCase() }) }),
|
|
41
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
42
|
+
/* @__PURE__ */ jsx("p", { className: "text-title truncate font-semibold", children: appName }),
|
|
43
|
+
/* @__PURE__ */ jsx("p", { className: "text-muted-foreground text-meta", children: eyebrow })
|
|
44
|
+
] })
|
|
45
|
+
] }),
|
|
46
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
47
|
+
/* @__PURE__ */ jsx("h1", { className: "text-display font-semibold tracking-tight", children: refused ? refusedTitle : "Sign in" }),
|
|
48
|
+
/* @__PURE__ */ jsx("p", { className: "text-muted-foreground text-body", children: refused ? refusedMessage : description })
|
|
49
|
+
] }),
|
|
50
|
+
features && features.length > 0 && !refused ? /* @__PURE__ */ jsx("ul", { className: "text-muted-foreground text-body space-y-1.5", children: features.slice(0, 3).map((feature) => /* @__PURE__ */ jsxs("li", { className: "flex gap-2", children: [
|
|
51
|
+
/* @__PURE__ */ jsx("span", { className: "text-foreground mt-1.5 h-1 w-1 shrink-0 rounded-full bg-current" }),
|
|
52
|
+
/* @__PURE__ */ jsx("span", { children: feature })
|
|
53
|
+
] }, feature)) }) : null,
|
|
54
|
+
error ? /* @__PURE__ */ jsx(
|
|
55
|
+
"p",
|
|
56
|
+
{
|
|
57
|
+
role: "alert",
|
|
58
|
+
className: "border-destructive/30 bg-destructive/5 text-destructive rounded-md border px-3 py-2 text-sm",
|
|
59
|
+
children: error
|
|
60
|
+
}
|
|
61
|
+
) : null,
|
|
62
|
+
/* @__PURE__ */ jsxs(
|
|
63
|
+
Button,
|
|
64
|
+
{
|
|
65
|
+
className: "w-full",
|
|
66
|
+
disabled: busy,
|
|
67
|
+
onClick: onSignIn,
|
|
68
|
+
"aria-busy": busy,
|
|
69
|
+
children: [
|
|
70
|
+
busy ? /* @__PURE__ */ jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin", "aria-hidden": true }) : null,
|
|
71
|
+
isSigningIn ? "Redirecting\u2026" : signInLabel
|
|
72
|
+
]
|
|
73
|
+
}
|
|
74
|
+
)
|
|
75
|
+
] })
|
|
76
|
+
}
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
function PanelSignInSkeleton({ className }) {
|
|
80
|
+
return /* @__PURE__ */ jsx(
|
|
81
|
+
"main",
|
|
82
|
+
{
|
|
83
|
+
className: cn(
|
|
84
|
+
"bg-background grid min-h-screen place-items-center p-4 sm:p-8",
|
|
85
|
+
className
|
|
86
|
+
),
|
|
87
|
+
children: /* @__PURE__ */ jsxs("div", { className: "border-border bg-card w-full max-w-md space-y-4 rounded-lg border p-8 shadow-sm", children: [
|
|
88
|
+
/* @__PURE__ */ jsx("div", { className: "bg-muted h-3 w-24 animate-pulse rounded" }),
|
|
89
|
+
/* @__PURE__ */ jsx("div", { className: "bg-muted h-8 w-48 animate-pulse rounded" }),
|
|
90
|
+
/* @__PURE__ */ jsx("div", { className: "bg-muted mt-7 h-10 w-full animate-pulse rounded-md" })
|
|
91
|
+
] })
|
|
92
|
+
}
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export {
|
|
97
|
+
PanelSignIn,
|
|
98
|
+
PanelSignInSkeleton
|
|
99
|
+
};
|
|
100
|
+
//# sourceMappingURL=chunk-PM2VE7DJ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/panel-sign-in.tsx"],"sourcesContent":["\"use client\";\n\nimport { Loader2 } from \"lucide-react\";\nimport * as React from \"react\";\n\nimport { Button } from \"./button\";\nimport { PanelBrandMark } from \"./panel-brand-mark\";\nimport { cn } from \"./utils\";\n\nexport type PanelSignInProps = {\n appName: string;\n /** Short line under the brand (e.g. \"Secure Google sign-in\"). */\n eyebrow?: string;\n /** One supporting sentence under the headline. */\n description?: string;\n /** Optional feature bullets — keep to ≤3; DESIGN.md: one job per surface. */\n features?: string[];\n brandIcon?: React.ReactNode;\n error?: string | null;\n /** Google signed in but panel access refused. */\n refused?: boolean;\n refusedTitle?: string;\n refusedMessage?: string;\n isSessionLoading?: boolean;\n isSigningIn?: boolean;\n onSignIn: () => void;\n signInLabel?: string;\n className?: string;\n};\n\n/**\n * DESIGN.md-compliant panel login: brand-first, ink neutrals, no purple glow.\n */\nexport function PanelSignIn({\n appName,\n eyebrow = \"Secure Google sign-in\",\n description = \"Use your work Google account to continue.\",\n features,\n brandIcon,\n error,\n refused = false,\n refusedTitle = \"Access denied\",\n refusedMessage = \"This Google account is signed in, but it is not provisioned for this panel.\",\n isSessionLoading = false,\n isSigningIn = false,\n onSignIn,\n signInLabel = \"Continue with Google\",\n className,\n}: PanelSignInProps) {\n const busy = isSessionLoading || isSigningIn;\n\n return (\n <main\n className={cn(\n \"bg-background text-foreground grid min-h-screen place-items-center p-4 sm:p-8\",\n className,\n )}\n >\n <section className=\"border-border bg-card w-full max-w-md space-y-6 rounded-lg border p-8 shadow-sm\">\n <div className=\"flex items-center gap-3\">\n <PanelBrandMark>\n {brandIcon ?? (\n <span className=\"text-sm font-semibold\" aria-hidden>\n {appName.slice(0, 1).toUpperCase()}\n </span>\n )}\n </PanelBrandMark>\n <div className=\"min-w-0\">\n <p className=\"text-title truncate font-semibold\">{appName}</p>\n <p className=\"text-muted-foreground text-meta\">{eyebrow}</p>\n </div>\n </div>\n\n <div className=\"space-y-2\">\n <h1 className=\"text-display font-semibold tracking-tight\">\n {refused ? refusedTitle : \"Sign in\"}\n </h1>\n <p className=\"text-muted-foreground text-body\">\n {refused ? refusedMessage : description}\n </p>\n </div>\n\n {features && features.length > 0 && !refused ? (\n <ul className=\"text-muted-foreground text-body space-y-1.5\">\n {features.slice(0, 3).map((feature) => (\n <li key={feature} className=\"flex gap-2\">\n <span className=\"text-foreground mt-1.5 h-1 w-1 shrink-0 rounded-full bg-current\" />\n <span>{feature}</span>\n </li>\n ))}\n </ul>\n ) : null}\n\n {error ? (\n <p\n role=\"alert\"\n className=\"border-destructive/30 bg-destructive/5 text-destructive rounded-md border px-3 py-2 text-sm\"\n >\n {error}\n </p>\n ) : null}\n\n <Button\n className=\"w-full\"\n disabled={busy}\n onClick={onSignIn}\n aria-busy={busy}\n >\n {busy ? (\n <Loader2 className=\"mr-2 h-4 w-4 animate-spin\" aria-hidden />\n ) : null}\n {isSigningIn ? \"Redirecting…\" : signInLabel}\n </Button>\n </section>\n </main>\n );\n}\n\nexport function PanelSignInSkeleton({ className }: { className?: string }) {\n return (\n <main\n className={cn(\n \"bg-background grid min-h-screen place-items-center p-4 sm:p-8\",\n className,\n )}\n >\n <div className=\"border-border bg-card w-full max-w-md space-y-4 rounded-lg border p-8 shadow-sm\">\n <div className=\"bg-muted h-3 w-24 animate-pulse rounded\" />\n <div className=\"bg-muted h-8 w-48 animate-pulse rounded\" />\n <div className=\"bg-muted mt-7 h-10 w-full animate-pulse rounded-md\" />\n </div>\n </main>\n );\n}\n"],"mappings":";;;;;;;;;;;AAEA,SAAS,eAAe;AA4DV,cAKJ,YALI;AA7BP,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA,UAAU;AAAA,EACV,cAAc;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV,eAAe;AAAA,EACf,iBAAiB;AAAA,EACjB,mBAAmB;AAAA,EACnB,cAAc;AAAA,EACd;AAAA,EACA,cAAc;AAAA,EACd;AACF,GAAqB;AACnB,QAAM,OAAO,oBAAoB;AAEjC,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MAEA,+BAAC,aAAQ,WAAU,mFACjB;AAAA,6BAAC,SAAI,WAAU,2BACb;AAAA,8BAAC,kBACE,uBACC,oBAAC,UAAK,WAAU,yBAAwB,eAAW,MAChD,kBAAQ,MAAM,GAAG,CAAC,EAAE,YAAY,GACnC,GAEJ;AAAA,UACA,qBAAC,SAAI,WAAU,WACb;AAAA,gCAAC,OAAE,WAAU,qCAAqC,mBAAQ;AAAA,YAC1D,oBAAC,OAAE,WAAU,mCAAmC,mBAAQ;AAAA,aAC1D;AAAA,WACF;AAAA,QAEA,qBAAC,SAAI,WAAU,aACb;AAAA,8BAAC,QAAG,WAAU,6CACX,oBAAU,eAAe,WAC5B;AAAA,UACA,oBAAC,OAAE,WAAU,mCACV,oBAAU,iBAAiB,aAC9B;AAAA,WACF;AAAA,QAEC,YAAY,SAAS,SAAS,KAAK,CAAC,UACnC,oBAAC,QAAG,WAAU,+CACX,mBAAS,MAAM,GAAG,CAAC,EAAE,IAAI,CAAC,YACzB,qBAAC,QAAiB,WAAU,cAC1B;AAAA,8BAAC,UAAK,WAAU,mEAAkE;AAAA,UAClF,oBAAC,UAAM,mBAAQ;AAAA,aAFR,OAGT,CACD,GACH,IACE;AAAA,QAEH,QACC;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,WAAU;AAAA,YAET;AAAA;AAAA,QACH,IACE;AAAA,QAEJ;AAAA,UAAC;AAAA;AAAA,YACC,WAAU;AAAA,YACV,UAAU;AAAA,YACV,SAAS;AAAA,YACT,aAAW;AAAA,YAEV;AAAA,qBACC,oBAAC,WAAQ,WAAU,6BAA4B,eAAW,MAAC,IACzD;AAAA,cACH,cAAc,sBAAiB;AAAA;AAAA;AAAA,QAClC;AAAA,SACF;AAAA;AAAA,EACF;AAEJ;AAEO,SAAS,oBAAoB,EAAE,UAAU,GAA2B;AACzE,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MAEA,+BAAC,SAAI,WAAU,mFACb;AAAA,4BAAC,SAAI,WAAU,2CAA0C;AAAA,QACzD,oBAAC,SAAI,WAAU,2CAA0C;AAAA,QACzD,oBAAC,SAAI,WAAU,sDAAqD;AAAA,SACtE;AAAA;AAAA,EACF;AAEJ;","names":[]}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import {
|
|
2
|
+
cn
|
|
3
|
+
} from "./chunk-HCA5ODCD.js";
|
|
4
|
+
import {
|
|
5
|
+
writeToClipboard
|
|
6
|
+
} from "./chunk-Y5WCT6XN.js";
|
|
7
|
+
|
|
8
|
+
// src/copy-button.tsx
|
|
9
|
+
import { Check, Copy } from "lucide-react";
|
|
10
|
+
import * as React from "react";
|
|
11
|
+
import { jsx } from "react/jsx-runtime";
|
|
12
|
+
function CopyButton({
|
|
13
|
+
value,
|
|
14
|
+
label,
|
|
15
|
+
className
|
|
16
|
+
}) {
|
|
17
|
+
const [copied, setCopied] = React.useState(false);
|
|
18
|
+
React.useEffect(() => {
|
|
19
|
+
if (!copied) return;
|
|
20
|
+
const timer = window.setTimeout(() => setCopied(false), 1500);
|
|
21
|
+
return () => window.clearTimeout(timer);
|
|
22
|
+
}, [copied]);
|
|
23
|
+
return /* @__PURE__ */ jsx(
|
|
24
|
+
"button",
|
|
25
|
+
{
|
|
26
|
+
type: "button",
|
|
27
|
+
"aria-label": copied ? `${label} copied` : `Copy ${label}`,
|
|
28
|
+
title: copied ? "Copied" : `Copy ${label}`,
|
|
29
|
+
className: cn(
|
|
30
|
+
"text-muted-foreground hover:text-foreground hover:bg-muted focus-visible:ring-ring shrink-0 cursor-pointer rounded p-1 transition focus-visible:ring-2 focus-visible:outline-none",
|
|
31
|
+
className
|
|
32
|
+
),
|
|
33
|
+
onClick: () => {
|
|
34
|
+
void writeToClipboard(value).then(() => setCopied(true)).catch(() => void 0);
|
|
35
|
+
},
|
|
36
|
+
children: copied ? /* @__PURE__ */ jsx(Check, { className: "size-3.5 text-success", "aria-hidden": true }) : /* @__PURE__ */ jsx(Copy, { className: "size-3.5", "aria-hidden": true })
|
|
37
|
+
}
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export {
|
|
42
|
+
CopyButton
|
|
43
|
+
};
|
|
44
|
+
//# sourceMappingURL=chunk-PPYR3O3L.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/copy-button.tsx"],"sourcesContent":["\"use client\";\n\nimport { Check, Copy } from \"lucide-react\";\nimport * as React from \"react\";\n\nimport { writeToClipboard } from \"./clipboard\";\nimport { cn } from \"./utils\";\n\n/**\n * Copies one short string — an id, a title, a URL — and says so for a moment.\n *\n * The panel had this three times over, each with its own timeout and its own\n * silent-failure story. `writeToClipboard` is used rather than\n * `navigator.clipboard` directly because the latter is undefined on http\n * origins, which is exactly where this panel runs in local dev.\n */\nexport function CopyButton({\n value,\n label,\n className,\n}: {\n value: string;\n /** What is being copied, for the accessible name: \"card id\", \"title\". */\n label: string;\n className?: string;\n}) {\n const [copied, setCopied] = React.useState(false);\n\n React.useEffect(() => {\n if (!copied) return;\n const timer = window.setTimeout(() => setCopied(false), 1500);\n return () => window.clearTimeout(timer);\n }, [copied]);\n\n return (\n <button\n type=\"button\"\n aria-label={copied ? `${label} copied` : `Copy ${label}`}\n title={copied ? \"Copied\" : `Copy ${label}`}\n className={cn(\n \"text-muted-foreground hover:text-foreground hover:bg-muted focus-visible:ring-ring shrink-0 cursor-pointer rounded p-1 transition focus-visible:ring-2 focus-visible:outline-none\",\n className,\n )}\n onClick={() => {\n // A denied clipboard permission should not throw into the row.\n void writeToClipboard(value)\n .then(() => setCopied(true))\n .catch(() => undefined);\n }}\n >\n {copied ? (\n <Check className=\"size-3.5 text-success\" aria-hidden />\n ) : (\n <Copy className=\"size-3.5\" aria-hidden />\n )}\n </button>\n );\n}\n"],"mappings":";;;;;;;;AAEA,SAAS,OAAO,YAAY;AAC5B,YAAY,WAAW;AAgDf;AAnCD,SAAS,WAAW;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AACF,GAKG;AACD,QAAM,CAAC,QAAQ,SAAS,IAAU,eAAS,KAAK;AAEhD,EAAM,gBAAU,MAAM;AACpB,QAAI,CAAC,OAAQ;AACb,UAAM,QAAQ,OAAO,WAAW,MAAM,UAAU,KAAK,GAAG,IAAI;AAC5D,WAAO,MAAM,OAAO,aAAa,KAAK;AAAA,EACxC,GAAG,CAAC,MAAM,CAAC;AAEX,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,cAAY,SAAS,GAAG,KAAK,YAAY,QAAQ,KAAK;AAAA,MACtD,OAAO,SAAS,WAAW,QAAQ,KAAK;AAAA,MACxC,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MACA,SAAS,MAAM;AAEb,aAAK,iBAAiB,KAAK,EACxB,KAAK,MAAM,UAAU,IAAI,CAAC,EAC1B,MAAM,MAAM,MAAS;AAAA,MAC1B;AAAA,MAEC,mBACC,oBAAC,SAAM,WAAU,yBAAwB,eAAW,MAAC,IAErD,oBAAC,QAAK,WAAU,YAAW,eAAW,MAAC;AAAA;AAAA,EAE3C;AAEJ;","names":[]}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Button
|
|
3
|
+
} from "./chunk-KR3BCFP7.js";
|
|
4
|
+
|
|
5
|
+
// src/pagination.tsx
|
|
6
|
+
import { ChevronLeft, ChevronRight, MoreHorizontal } from "lucide-react";
|
|
7
|
+
import * as React from "react";
|
|
8
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
+
function Pagination({
|
|
10
|
+
currentPage,
|
|
11
|
+
totalPages,
|
|
12
|
+
onPageChange,
|
|
13
|
+
loading = false,
|
|
14
|
+
showPageInfo = true
|
|
15
|
+
}) {
|
|
16
|
+
const visiblePages = React.useMemo(() => {
|
|
17
|
+
const delta = 2;
|
|
18
|
+
const range = [];
|
|
19
|
+
const rangeWithDots = [];
|
|
20
|
+
for (let i = Math.max(2, currentPage - delta); i <= Math.min(totalPages - 1, currentPage + delta); i++) {
|
|
21
|
+
range.push(i);
|
|
22
|
+
}
|
|
23
|
+
if (currentPage - delta > 2) {
|
|
24
|
+
rangeWithDots.push(1, "...");
|
|
25
|
+
} else {
|
|
26
|
+
rangeWithDots.push(1);
|
|
27
|
+
}
|
|
28
|
+
rangeWithDots.push(...range);
|
|
29
|
+
if (currentPage + delta < totalPages - 1) {
|
|
30
|
+
rangeWithDots.push("...", totalPages);
|
|
31
|
+
} else if (totalPages > 1) {
|
|
32
|
+
rangeWithDots.push(totalPages);
|
|
33
|
+
}
|
|
34
|
+
return rangeWithDots;
|
|
35
|
+
}, [currentPage, totalPages]);
|
|
36
|
+
if (totalPages <= 1) return null;
|
|
37
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-between gap-4 sm:flex-row", children: [
|
|
38
|
+
showPageInfo ? /* @__PURE__ */ jsxs("div", { className: "text-muted-foreground order-2 text-sm sm:order-1", children: [
|
|
39
|
+
"Page ",
|
|
40
|
+
currentPage,
|
|
41
|
+
" of ",
|
|
42
|
+
totalPages
|
|
43
|
+
] }) : null,
|
|
44
|
+
/* @__PURE__ */ jsxs("div", { className: "order-1 flex items-center space-x-1 sm:order-2 sm:space-x-2", children: [
|
|
45
|
+
/* @__PURE__ */ jsx(
|
|
46
|
+
Button,
|
|
47
|
+
{
|
|
48
|
+
variant: "outline",
|
|
49
|
+
size: "sm",
|
|
50
|
+
onClick: () => onPageChange(currentPage - 1),
|
|
51
|
+
disabled: currentPage <= 1 || loading,
|
|
52
|
+
className: "h-8 min-w-8 px-2",
|
|
53
|
+
"aria-label": "Previous page",
|
|
54
|
+
children: /* @__PURE__ */ jsx(ChevronLeft, { className: "h-4 w-4" })
|
|
55
|
+
}
|
|
56
|
+
),
|
|
57
|
+
/* @__PURE__ */ jsx("div", { className: "flex max-w-[200px] items-center space-x-1 overflow-x-auto sm:max-w-none", children: visiblePages.map(
|
|
58
|
+
(page, index) => page === "..." ? /* @__PURE__ */ jsx(
|
|
59
|
+
"div",
|
|
60
|
+
{
|
|
61
|
+
className: "flex h-8 w-8 shrink-0 items-center justify-center",
|
|
62
|
+
children: /* @__PURE__ */ jsx(MoreHorizontal, { className: "h-4 w-4" })
|
|
63
|
+
},
|
|
64
|
+
`dots-${index}`
|
|
65
|
+
) : /* @__PURE__ */ jsx(
|
|
66
|
+
Button,
|
|
67
|
+
{
|
|
68
|
+
variant: page === currentPage ? "default" : "outline",
|
|
69
|
+
size: "sm",
|
|
70
|
+
onClick: () => onPageChange(page),
|
|
71
|
+
disabled: loading,
|
|
72
|
+
className: "h-8 min-w-8 shrink-0 px-2",
|
|
73
|
+
"aria-current": page === currentPage ? "page" : void 0,
|
|
74
|
+
children: page
|
|
75
|
+
},
|
|
76
|
+
page
|
|
77
|
+
)
|
|
78
|
+
) }),
|
|
79
|
+
/* @__PURE__ */ jsx(
|
|
80
|
+
Button,
|
|
81
|
+
{
|
|
82
|
+
variant: "outline",
|
|
83
|
+
size: "sm",
|
|
84
|
+
onClick: () => onPageChange(currentPage + 1),
|
|
85
|
+
disabled: currentPage >= totalPages || loading,
|
|
86
|
+
className: "h-8 min-w-8 px-2",
|
|
87
|
+
"aria-label": "Next page",
|
|
88
|
+
children: /* @__PURE__ */ jsx(ChevronRight, { className: "h-4 w-4" })
|
|
89
|
+
}
|
|
90
|
+
)
|
|
91
|
+
] })
|
|
92
|
+
] });
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export {
|
|
96
|
+
Pagination
|
|
97
|
+
};
|
|
98
|
+
//# sourceMappingURL=chunk-PUTC52SI.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/pagination.tsx"],"sourcesContent":["\"use client\";\n\nimport { ChevronLeft, ChevronRight, MoreHorizontal } from \"lucide-react\";\nimport * as React from \"react\";\n\nimport { Button } from \"./button\";\n\nexport type PaginationProps = {\n currentPage: number;\n totalPages: number;\n onPageChange: (page: number) => void;\n loading?: boolean;\n showPageInfo?: boolean;\n};\n\n/**\n * Numbered pager for list panels. Hides itself when there is only one page.\n */\nexport function Pagination({\n currentPage,\n totalPages,\n onPageChange,\n loading = false,\n showPageInfo = true,\n}: PaginationProps) {\n const visiblePages = React.useMemo(() => {\n const delta = 2;\n const range: number[] = [];\n const rangeWithDots: Array<number | \"...\"> = [];\n\n for (\n let i = Math.max(2, currentPage - delta);\n i <= Math.min(totalPages - 1, currentPage + delta);\n i++\n ) {\n range.push(i);\n }\n\n if (currentPage - delta > 2) {\n rangeWithDots.push(1, \"...\");\n } else {\n rangeWithDots.push(1);\n }\n\n rangeWithDots.push(...range);\n\n if (currentPage + delta < totalPages - 1) {\n rangeWithDots.push(\"...\", totalPages);\n } else if (totalPages > 1) {\n rangeWithDots.push(totalPages);\n }\n\n return rangeWithDots;\n }, [currentPage, totalPages]);\n\n if (totalPages <= 1) return null;\n\n return (\n <div className=\"flex flex-col items-center justify-between gap-4 sm:flex-row\">\n {showPageInfo ? (\n <div className=\"text-muted-foreground order-2 text-sm sm:order-1\">\n Page {currentPage} of {totalPages}\n </div>\n ) : null}\n\n <div className=\"order-1 flex items-center space-x-1 sm:order-2 sm:space-x-2\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => onPageChange(currentPage - 1)}\n disabled={currentPage <= 1 || loading}\n className=\"h-8 min-w-8 px-2\"\n aria-label=\"Previous page\"\n >\n <ChevronLeft className=\"h-4 w-4\" />\n </Button>\n\n <div className=\"flex max-w-[200px] items-center space-x-1 overflow-x-auto sm:max-w-none\">\n {visiblePages.map((page, index) =>\n page === \"...\" ? (\n <div\n key={`dots-${index}`}\n className=\"flex h-8 w-8 shrink-0 items-center justify-center\"\n >\n <MoreHorizontal className=\"h-4 w-4\" />\n </div>\n ) : (\n <Button\n key={page}\n variant={page === currentPage ? \"default\" : \"outline\"}\n size=\"sm\"\n onClick={() => onPageChange(page)}\n disabled={loading}\n className=\"h-8 min-w-8 shrink-0 px-2\"\n aria-current={page === currentPage ? \"page\" : undefined}\n >\n {page}\n </Button>\n ),\n )}\n </div>\n\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => onPageChange(currentPage + 1)}\n disabled={currentPage >= totalPages || loading}\n className=\"h-8 min-w-8 px-2\"\n aria-label=\"Next page\"\n >\n <ChevronRight className=\"h-4 w-4\" />\n </Button>\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;AAEA,SAAS,aAAa,cAAc,sBAAsB;AAC1D,YAAY,WAAW;AAyDf,SAcE,KAdF;AA1CD,SAAS,WAAW;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV,eAAe;AACjB,GAAoB;AAClB,QAAM,eAAqB,cAAQ,MAAM;AACvC,UAAM,QAAQ;AACd,UAAM,QAAkB,CAAC;AACzB,UAAM,gBAAuC,CAAC;AAE9C,aACM,IAAI,KAAK,IAAI,GAAG,cAAc,KAAK,GACvC,KAAK,KAAK,IAAI,aAAa,GAAG,cAAc,KAAK,GACjD,KACA;AACA,YAAM,KAAK,CAAC;AAAA,IACd;AAEA,QAAI,cAAc,QAAQ,GAAG;AAC3B,oBAAc,KAAK,GAAG,KAAK;AAAA,IAC7B,OAAO;AACL,oBAAc,KAAK,CAAC;AAAA,IACtB;AAEA,kBAAc,KAAK,GAAG,KAAK;AAE3B,QAAI,cAAc,QAAQ,aAAa,GAAG;AACxC,oBAAc,KAAK,OAAO,UAAU;AAAA,IACtC,WAAW,aAAa,GAAG;AACzB,oBAAc,KAAK,UAAU;AAAA,IAC/B;AAEA,WAAO;AAAA,EACT,GAAG,CAAC,aAAa,UAAU,CAAC;AAE5B,MAAI,cAAc,EAAG,QAAO;AAE5B,SACE,qBAAC,SAAI,WAAU,gEACZ;AAAA,mBACC,qBAAC,SAAI,WAAU,oDAAmD;AAAA;AAAA,MAC1D;AAAA,MAAY;AAAA,MAAK;AAAA,OACzB,IACE;AAAA,IAEJ,qBAAC,SAAI,WAAU,+DACb;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,SAAQ;AAAA,UACR,MAAK;AAAA,UACL,SAAS,MAAM,aAAa,cAAc,CAAC;AAAA,UAC3C,UAAU,eAAe,KAAK;AAAA,UAC9B,WAAU;AAAA,UACV,cAAW;AAAA,UAEX,8BAAC,eAAY,WAAU,WAAU;AAAA;AAAA,MACnC;AAAA,MAEA,oBAAC,SAAI,WAAU,2EACZ,uBAAa;AAAA,QAAI,CAAC,MAAM,UACvB,SAAS,QACP;AAAA,UAAC;AAAA;AAAA,YAEC,WAAU;AAAA,YAEV,8BAAC,kBAAe,WAAU,WAAU;AAAA;AAAA,UAH/B,QAAQ,KAAK;AAAA,QAIpB,IAEA;AAAA,UAAC;AAAA;AAAA,YAEC,SAAS,SAAS,cAAc,YAAY;AAAA,YAC5C,MAAK;AAAA,YACL,SAAS,MAAM,aAAa,IAAI;AAAA,YAChC,UAAU;AAAA,YACV,WAAU;AAAA,YACV,gBAAc,SAAS,cAAc,SAAS;AAAA,YAE7C;AAAA;AAAA,UARI;AAAA,QASP;AAAA,MAEJ,GACF;AAAA,MAEA;AAAA,QAAC;AAAA;AAAA,UACC,SAAQ;AAAA,UACR,MAAK;AAAA,UACL,SAAS,MAAM,aAAa,cAAc,CAAC;AAAA,UAC3C,UAAU,eAAe,cAAc;AAAA,UACvC,WAAU;AAAA,UACV,cAAW;AAAA,UAEX,8BAAC,gBAAa,WAAU,WAAU;AAAA;AAAA,MACpC;AAAA,OACF;AAAA,KACF;AAEJ;","names":[]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import {
|
|
2
|
+
cn
|
|
3
|
+
} from "./chunk-HCA5ODCD.js";
|
|
4
|
+
|
|
5
|
+
// src/input.tsx
|
|
6
|
+
import * as React from "react";
|
|
7
|
+
import { jsx } from "react/jsx-runtime";
|
|
8
|
+
var inputClass = "h-9 w-full rounded-md border border-border bg-background px-3 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50";
|
|
9
|
+
var Input = React.forwardRef(
|
|
10
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx("input", { ref, className: cn(inputClass, className), ...props })
|
|
11
|
+
);
|
|
12
|
+
Input.displayName = "Input";
|
|
13
|
+
|
|
14
|
+
export {
|
|
15
|
+
inputClass,
|
|
16
|
+
Input
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=chunk-PWAKTEXF.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/input.tsx"],"sourcesContent":["import * as React from \"react\";\n\nimport { cn } from \"./utils\";\n\nexport const inputClass =\n \"h-9 w-full rounded-md border border-border bg-background px-3 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50\";\n\nexport type InputProps = React.InputHTMLAttributes<HTMLInputElement>;\n\nexport const Input = React.forwardRef<HTMLInputElement, InputProps>(\n ({ className, ...props }, ref) => (\n <input ref={ref} className={cn(inputClass, className)} {...props} />\n ),\n);\n\nInput.displayName = \"Input\";\n"],"mappings":";;;;;AAAA,YAAY,WAAW;AAWnB;AAPG,IAAM,aACX;AAIK,IAAM,QAAc;AAAA,EACzB,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QACxB,oBAAC,WAAM,KAAU,WAAW,GAAG,YAAY,SAAS,GAAI,GAAG,OAAO;AAEtE;AAEA,MAAM,cAAc;","names":[]}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import {
|
|
2
|
+
cn
|
|
3
|
+
} from "./chunk-HCA5ODCD.js";
|
|
4
|
+
|
|
5
|
+
// src/label.tsx
|
|
6
|
+
import * as React from "react";
|
|
7
|
+
import { jsx } from "react/jsx-runtime";
|
|
8
|
+
var Label = React.forwardRef(
|
|
9
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
10
|
+
"label",
|
|
11
|
+
{
|
|
12
|
+
ref,
|
|
13
|
+
className: cn(
|
|
14
|
+
"text-sm leading-none font-medium peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
|
|
15
|
+
className
|
|
16
|
+
),
|
|
17
|
+
...props
|
|
18
|
+
}
|
|
19
|
+
)
|
|
20
|
+
);
|
|
21
|
+
Label.displayName = "Label";
|
|
22
|
+
|
|
23
|
+
export {
|
|
24
|
+
Label
|
|
25
|
+
};
|
|
26
|
+
//# sourceMappingURL=chunk-QTFWORA7.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/label.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\n\nimport { cn } from \"./utils\";\n\nexport type LabelProps = React.LabelHTMLAttributes<HTMLLabelElement>;\n\n/** Form label — pair with a native control via `htmlFor`. */\nexport const Label = React.forwardRef<HTMLLabelElement, LabelProps>(\n ({ className, ...props }, ref) => (\n <label\n ref={ref}\n className={cn(\n \"text-sm leading-none font-medium peer-disabled:cursor-not-allowed peer-disabled:opacity-70\",\n className,\n )}\n {...props}\n />\n ),\n);\n\nLabel.displayName = \"Label\";\n"],"mappings":";;;;;AAEA,YAAY,WAAW;AASnB;AAFG,IAAM,QAAc;AAAA,EACzB,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QACxB;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;AAEA,MAAM,cAAc;","names":[]}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import {
|
|
2
|
+
cn
|
|
3
|
+
} from "./chunk-HCA5ODCD.js";
|
|
4
|
+
|
|
5
|
+
// src/page-header.tsx
|
|
6
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
function PageHeader({
|
|
8
|
+
title,
|
|
9
|
+
description,
|
|
10
|
+
eyebrow,
|
|
11
|
+
actions,
|
|
12
|
+
className
|
|
13
|
+
}) {
|
|
14
|
+
const heading = /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
15
|
+
eyebrow,
|
|
16
|
+
/* @__PURE__ */ jsx(
|
|
17
|
+
"h1",
|
|
18
|
+
{
|
|
19
|
+
className: cn(
|
|
20
|
+
"text-2xl font-semibold tracking-tight",
|
|
21
|
+
eyebrow != null && "mt-1"
|
|
22
|
+
),
|
|
23
|
+
children: title
|
|
24
|
+
}
|
|
25
|
+
),
|
|
26
|
+
description != null ? /* @__PURE__ */ jsx("p", { className: "text-muted-foreground mt-1 text-sm", children: description }) : null
|
|
27
|
+
] });
|
|
28
|
+
if (!actions) {
|
|
29
|
+
return /* @__PURE__ */ jsx("div", { className, children: heading });
|
|
30
|
+
}
|
|
31
|
+
return /* @__PURE__ */ jsxs(
|
|
32
|
+
"div",
|
|
33
|
+
{
|
|
34
|
+
className: cn(
|
|
35
|
+
"flex flex-wrap items-center justify-between gap-3",
|
|
36
|
+
className
|
|
37
|
+
),
|
|
38
|
+
children: [
|
|
39
|
+
heading,
|
|
40
|
+
actions
|
|
41
|
+
]
|
|
42
|
+
}
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export {
|
|
47
|
+
PageHeader
|
|
48
|
+
};
|
|
49
|
+
//# sourceMappingURL=chunk-RUPL2H6V.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/page-header.tsx"],"sourcesContent":["import * as React from \"react\";\n\nimport { cn } from \"./utils\";\n\n/**\n * The title block every panel opens with.\n *\n * Twenty Managers wrote the same `<h1>` and subtitle by hand, differing only in\n * whether the row said `gap-3` or `gap-x-4 gap-y-2` and whether the inner block\n * carried `min-w-0` — differences nobody chose, which is what made them worth\n * removing.\n *\n * `description` takes a node rather than a string because several panels put a\n * `<code>` in theirs, naming the Firebase field they write. That is the useful\n * kind of subtitle and it should not have to opt out of the shared component to\n * stay.\n *\n * `min-w-0` is not optional here. Without it a long title refuses to shrink and\n * pushes the actions off the row instead of wrapping — which is the bug the\n * three panels that set it had already hit, and the seven that did not had not\n * yet.\n */\nexport interface PageHeaderProps {\n title: React.ReactNode;\n description?: React.ReactNode;\n /**\n * Sits above the title: a breadcrumb, or the back link the filter editors\n * use. Four panels had one, each spacing it by hand.\n */\n eyebrow?: React.ReactNode;\n /** Buttons belonging to the page, laid out at the end of the title row. */\n actions?: React.ReactNode;\n className?: string;\n}\n\nexport function PageHeader({\n title,\n description,\n eyebrow,\n actions,\n className,\n}: PageHeaderProps) {\n const heading = (\n <div className=\"min-w-0\">\n {eyebrow}\n <h1\n className={cn(\n \"text-2xl font-semibold tracking-tight\",\n eyebrow != null && \"mt-1\",\n )}\n >\n {title}\n </h1>\n {description != null ? (\n <p className=\"text-muted-foreground mt-1 text-sm\">{description}</p>\n ) : null}\n </div>\n );\n\n if (!actions) {\n return <div className={className}>{heading}</div>;\n }\n\n return (\n <div\n className={cn(\n \"flex flex-wrap items-center justify-between gap-3\",\n className,\n )}\n >\n {heading}\n {actions}\n </div>\n );\n}\n"],"mappings":";;;;;AA2CI,SAEE,KAFF;AARG,SAAS,WAAW;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAoB;AAClB,QAAM,UACJ,qBAAC,SAAI,WAAU,WACZ;AAAA;AAAA,IACD;AAAA,MAAC;AAAA;AAAA,QACC,WAAW;AAAA,UACT;AAAA,UACA,WAAW,QAAQ;AAAA,QACrB;AAAA,QAEC;AAAA;AAAA,IACH;AAAA,IACC,eAAe,OACd,oBAAC,OAAE,WAAU,sCAAsC,uBAAY,IAC7D;AAAA,KACN;AAGF,MAAI,CAAC,SAAS;AACZ,WAAO,oBAAC,SAAI,WAAuB,mBAAQ;AAAA,EAC7C;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MAEC;AAAA;AAAA,QACA;AAAA;AAAA;AAAA,EACH;AAEJ;","names":[]}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import {
|
|
2
|
+
StatePanel
|
|
3
|
+
} from "./chunk-G4ZQUSAJ.js";
|
|
4
|
+
import {
|
|
5
|
+
Alert
|
|
6
|
+
} from "./chunk-ZP252OJZ.js";
|
|
7
|
+
|
|
8
|
+
// src/feature-access-gate.tsx
|
|
9
|
+
import { Fragment, jsx } from "react/jsx-runtime";
|
|
10
|
+
function FeatureAccessGate({
|
|
11
|
+
isLoading,
|
|
12
|
+
allowed,
|
|
13
|
+
deniedMessage,
|
|
14
|
+
children
|
|
15
|
+
}) {
|
|
16
|
+
if (isLoading) {
|
|
17
|
+
return /* @__PURE__ */ jsx(StatePanel, { loading: true, className: "p-6", children: "Checking permissions\u2026" });
|
|
18
|
+
}
|
|
19
|
+
if (!allowed) {
|
|
20
|
+
return /* @__PURE__ */ jsx(Alert, { children: deniedMessage });
|
|
21
|
+
}
|
|
22
|
+
return /* @__PURE__ */ jsx(Fragment, { children });
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export {
|
|
26
|
+
FeatureAccessGate
|
|
27
|
+
};
|
|
28
|
+
//# sourceMappingURL=chunk-S7PVZAPL.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/feature-access-gate.tsx"],"sourcesContent":["import * as React from \"react\";\n\nimport { Alert } from \"./alert\";\nimport { StatePanel } from \"./state-panel\";\n\ntype FeatureAccessGateProps = {\n isLoading?: boolean;\n allowed: boolean;\n deniedMessage: React.ReactNode;\n children: React.ReactNode;\n};\n\n/**\n * Shared loading / denied shell for feature Managers (showcase, headers, …).\n */\nexport function FeatureAccessGate({\n isLoading,\n allowed,\n deniedMessage,\n children,\n}: FeatureAccessGateProps) {\n if (isLoading) {\n return (\n <StatePanel loading className=\"p-6\">\n Checking permissions…\n </StatePanel>\n );\n }\n\n if (!allowed) {\n // `Alert`, not a hand-rolled banner: this is the denial surface for\n // seventeen panels, and it was the one copy the Alert migration missed —\n // so being refused a panel announced nothing to a screen reader.\n return <Alert>{deniedMessage}</Alert>;\n }\n\n return <>{children}</>;\n}\n"],"mappings":";;;;;;;;AAuBM,SAaG,UAbH;AARC,SAAS,kBAAkB;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA2B;AACzB,MAAI,WAAW;AACb,WACE,oBAAC,cAAW,SAAO,MAAC,WAAU,OAAM,wCAEpC;AAAA,EAEJ;AAEA,MAAI,CAAC,SAAS;AAIZ,WAAO,oBAAC,SAAO,yBAAc;AAAA,EAC/B;AAEA,SAAO,gCAAG,UAAS;AACrB;","names":[]}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import {
|
|
2
|
+
cn
|
|
3
|
+
} from "./chunk-HCA5ODCD.js";
|
|
4
|
+
|
|
5
|
+
// src/badge.tsx
|
|
6
|
+
import * as React from "react";
|
|
7
|
+
import { cva } from "class-variance-authority";
|
|
8
|
+
import { jsx } from "react/jsx-runtime";
|
|
9
|
+
var badgeVariants = cva(
|
|
10
|
+
"inline-flex items-center gap-1 rounded font-medium whitespace-nowrap",
|
|
11
|
+
{
|
|
12
|
+
variants: {
|
|
13
|
+
variant: {
|
|
14
|
+
neutral: "bg-muted text-muted-foreground",
|
|
15
|
+
success: "bg-success/15 text-success",
|
|
16
|
+
warning: "bg-warning/15 text-warning",
|
|
17
|
+
danger: "bg-destructive/15 text-destructive",
|
|
18
|
+
info: "bg-info/15 text-info"
|
|
19
|
+
},
|
|
20
|
+
size: {
|
|
21
|
+
/** Inline chips — a category, a tenant, a permission. */
|
|
22
|
+
sm: "px-1.5 py-0.5 text-xs",
|
|
23
|
+
/** A row's status. */
|
|
24
|
+
md: "px-2 py-0.5 text-xs"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
defaultVariants: {
|
|
28
|
+
variant: "neutral",
|
|
29
|
+
size: "md"
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
);
|
|
33
|
+
var Badge = React.forwardRef(
|
|
34
|
+
({ className, variant, size, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
35
|
+
"span",
|
|
36
|
+
{
|
|
37
|
+
ref,
|
|
38
|
+
className: cn(badgeVariants({ variant, size }), className),
|
|
39
|
+
...props
|
|
40
|
+
}
|
|
41
|
+
)
|
|
42
|
+
);
|
|
43
|
+
Badge.displayName = "Badge";
|
|
44
|
+
|
|
45
|
+
export {
|
|
46
|
+
badgeVariants,
|
|
47
|
+
Badge
|
|
48
|
+
};
|
|
49
|
+
//# sourceMappingURL=chunk-SQDV2AKJ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/badge.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\n\nimport { cn } from \"./utils\";\n\n/**\n * The status pill every list panel was spelling out by hand.\n *\n * Variants are semantic rather than named after a colour, because the same\n * status means the same thing on every panel and should not have to be\n * re-decided per table — Deleted was `bg-rose-100 text-rose-800` in one place\n * and `text-rose-900` two files away.\n *\n * These stay light-on-dark-text in both themes on purpose. A pill is a small\n * block of colour whose whole job is to be picked out of a row of text, and\n * inverting it per theme made the same status read as two different states.\n */\nconst badgeVariants = cva(\n \"inline-flex items-center gap-1 rounded font-medium whitespace-nowrap\",\n {\n variants: {\n variant: {\n neutral: \"bg-muted text-muted-foreground\",\n success: \"bg-success/15 text-success\",\n warning: \"bg-warning/15 text-warning\",\n danger: \"bg-destructive/15 text-destructive\",\n info: \"bg-info/15 text-info\",\n },\n size: {\n /** Inline chips — a category, a tenant, a permission. */\n sm: \"px-1.5 py-0.5 text-xs\",\n /** A row's status. */\n md: \"px-2 py-0.5 text-xs\",\n },\n },\n defaultVariants: {\n variant: \"neutral\",\n size: \"md\",\n },\n },\n);\n\nexport interface BadgeProps\n extends\n React.HTMLAttributes<HTMLSpanElement>,\n VariantProps<typeof badgeVariants> {}\n\nexport const Badge = React.forwardRef<HTMLSpanElement, BadgeProps>(\n ({ className, variant, size, ...props }, ref) => (\n <span\n ref={ref}\n className={cn(badgeVariants({ variant, size }), className)}\n {...props}\n />\n ),\n);\n\nBadge.displayName = \"Badge\";\n\nexport { badgeVariants };\n"],"mappings":";;;;;AAAA,YAAY,WAAW;AACvB,SAAS,WAA8B;AAgDnC;AAhCJ,IAAM,gBAAgB;AAAA,EACpB;AAAA,EACA;AAAA,IACE,UAAU;AAAA,MACR,SAAS;AAAA,QACP,SAAS;AAAA,QACT,SAAS;AAAA,QACT,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,MAAM;AAAA,MACR;AAAA,MACA,MAAM;AAAA;AAAA,QAEJ,IAAI;AAAA;AAAA,QAEJ,IAAI;AAAA,MACN;AAAA,IACF;AAAA,IACA,iBAAiB;AAAA,MACf,SAAS;AAAA,MACT,MAAM;AAAA,IACR;AAAA,EACF;AACF;AAOO,IAAM,QAAc;AAAA,EACzB,CAAC,EAAE,WAAW,SAAS,MAAM,GAAG,MAAM,GAAG,QACvC;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,WAAW,GAAG,cAAc,EAAE,SAAS,KAAK,CAAC,GAAG,SAAS;AAAA,MACxD,GAAG;AAAA;AAAA,EACN;AAEJ;AAEA,MAAM,cAAc;","names":[]}
|