@orangecheck/app-design 0.6.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -6
- package/dist/brand.js.map +1 -1
- package/dist/brand.mjs.map +1 -1
- package/dist/chrome.d.mts +78 -55
- package/dist/chrome.d.ts +78 -55
- package/dist/chrome.js +1100 -59
- package/dist/chrome.js.map +1 -1
- package/dist/chrome.mjs +1091 -61
- package/dist/chrome.mjs.map +1 -1
- package/dist/code.d.mts +52 -0
- package/dist/code.d.ts +52 -0
- package/dist/code.js +534 -0
- package/dist/code.js.map +1 -0
- package/dist/code.mjs +522 -0
- package/dist/code.mjs.map +1 -0
- package/dist/components.d.mts +216 -42
- package/dist/components.d.ts +216 -42
- package/dist/components.js +3350 -100
- package/dist/components.js.map +1 -1
- package/dist/components.mjs +3293 -103
- package/dist/components.mjs.map +1 -1
- package/dist/docs-DhnstueM.d.ts +219 -0
- package/dist/docs-DiR6s43s.d.mts +219 -0
- package/dist/family.d.mts +2 -0
- package/dist/family.d.ts +2 -0
- package/dist/family.js +167 -0
- package/dist/family.js.map +1 -0
- package/dist/family.mjs +154 -0
- package/dist/family.mjs.map +1 -0
- package/dist/format.d.mts +12 -0
- package/dist/format.d.ts +12 -0
- package/dist/format.js +65 -0
- package/dist/format.js.map +1 -0
- package/dist/format.mjs +58 -0
- package/dist/format.mjs.map +1 -0
- package/dist/hero-Dn37il-9.d.mts +31 -0
- package/dist/hero-Dn37il-9.d.ts +31 -0
- package/dist/index-C6hDqOOS.d.mts +58 -0
- package/dist/index-C6hDqOOS.d.ts +58 -0
- package/dist/index.d.mts +12 -3
- package/dist/index.d.ts +12 -3
- package/dist/index.js +4319 -295
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +4219 -298
- package/dist/index.mjs.map +1 -1
- package/dist/mdx.d.mts +58 -0
- package/dist/mdx.d.ts +58 -0
- package/dist/mdx.js +1712 -0
- package/dist/mdx.js.map +1 -0
- package/dist/mdx.mjs +1685 -0
- package/dist/mdx.mjs.map +1 -0
- package/dist/primitives.d.mts +73 -5
- package/dist/primitives.d.ts +73 -5
- package/dist/primitives.js +331 -8
- package/dist/primitives.js.map +1 -1
- package/dist/primitives.mjs +320 -11
- package/dist/primitives.mjs.map +1 -1
- package/dist/session.d.mts +18 -0
- package/dist/session.d.ts +18 -0
- package/dist/session.js +432 -0
- package/dist/session.js.map +1 -0
- package/dist/session.mjs +401 -0
- package/dist/session.mjs.map +1 -0
- package/dist/status-badge-BEOxeY9j.d.ts +13 -0
- package/dist/status-badge-DRwGhB0h.d.mts +13 -0
- package/dist/styles/code.css +97 -0
- package/dist/styles/fonts.css +1 -1
- package/dist/styles/theme.css +2 -0
- package/dist/styles/tokens.css +44 -2
- package/dist/styles.css +1 -0
- package/dist/tokens.d.mts +3 -1
- package/dist/tokens.d.ts +3 -1
- package/dist/tokens.js +5 -3
- package/dist/tokens.js.map +1 -1
- package/dist/tokens.mjs +5 -3
- package/dist/tokens.mjs.map +1 -1
- package/dist/tool-shell-B1C7ahKE.d.ts +81 -0
- package/dist/tool-shell-BDx_N5ai.d.mts +81 -0
- package/dist/tools-BggNN5DV.d.ts +131 -0
- package/dist/tools-DFIxIj5p.d.mts +131 -0
- package/package.json +38 -2
package/dist/primitives.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Slot } from '@radix-ui/react-slot';
|
|
2
2
|
import { cva } from 'class-variance-authority';
|
|
3
|
-
import { forwardRef,
|
|
3
|
+
import { forwardRef, useContext, createContext, useRef, useState, useCallback, useEffect, createElement, useId, isValidElement, cloneElement, useSyncExternalStore, useMemo } from 'react';
|
|
4
4
|
import { clsx } from 'clsx';
|
|
5
5
|
import { extendTailwindMerge } from 'tailwind-merge';
|
|
6
6
|
import * as SeparatorPrimitive from '@radix-ui/react-separator';
|
|
@@ -12,12 +12,13 @@ import * as LabelPrimitive from '@radix-ui/react-label';
|
|
|
12
12
|
import * as RadioGroupPrimitive from '@radix-ui/react-radio-group';
|
|
13
13
|
import * as SelectPrimitive from '@radix-ui/react-select';
|
|
14
14
|
import * as SwitchPrimitive from '@radix-ui/react-switch';
|
|
15
|
-
import { ChevronDown, Check, X } from 'lucide-react';
|
|
15
|
+
import { ChevronDown, Check, X, ChevronLeft, ChevronRight } from 'lucide-react';
|
|
16
16
|
import * as DialogPrimitive from '@radix-ui/react-dialog';
|
|
17
17
|
import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
|
|
18
18
|
import * as PopoverPrimitive from '@radix-ui/react-popover';
|
|
19
19
|
import * as TooltipPrimitive from '@radix-ui/react-tooltip';
|
|
20
20
|
import * as TabsPrimitive from '@radix-ui/react-tabs';
|
|
21
|
+
import QRCode from 'qrcode';
|
|
21
22
|
|
|
22
23
|
var merge = extendTailwindMerge({
|
|
23
24
|
extend: {
|
|
@@ -206,13 +207,13 @@ var badgeVariants = cva(
|
|
|
206
207
|
tone: {
|
|
207
208
|
neutral: "border-border bg-card text-foreground",
|
|
208
209
|
muted: "border-transparent bg-muted text-muted-foreground",
|
|
209
|
-
brand: "border-transparent bg-[color-mix(in_oklab,var(--oca-orange)
|
|
210
|
+
brand: "border-transparent bg-[color-mix(in_oklab,var(--oca-orange)_9%,var(--card))] text-oca-accent-ink",
|
|
210
211
|
danger: "border-transparent bg-[color-mix(in_oklab,var(--destructive)_12%,var(--card))] text-destructive",
|
|
211
212
|
// A good state is a neutral pill with a green dot, not a green pill.
|
|
212
213
|
success: GOOD_DOT,
|
|
213
214
|
// Aliases kept so older call sites keep compiling: attention is
|
|
214
215
|
// the brand accent, information is neutral.
|
|
215
|
-
warning: "border-transparent bg-[color-mix(in_oklab,var(--oca-orange)
|
|
216
|
+
warning: "border-transparent bg-[color-mix(in_oklab,var(--oca-orange)_9%,var(--card))] text-oca-accent-ink",
|
|
216
217
|
info: "border-border bg-card text-foreground",
|
|
217
218
|
// Inverted in dark mode, where ink would sit on a card of nearly its own colour.
|
|
218
219
|
ink: "border-transparent bg-oca-ink text-oca-ink-foreground dark:bg-foreground dark:text-background",
|
|
@@ -250,6 +251,30 @@ function StatusPill({
|
|
|
250
251
|
}
|
|
251
252
|
);
|
|
252
253
|
}
|
|
254
|
+
var WORD = {
|
|
255
|
+
live: "Live",
|
|
256
|
+
testing: "In testing",
|
|
257
|
+
"not-yet": "Not yet",
|
|
258
|
+
paused: "Paused",
|
|
259
|
+
good: "Good",
|
|
260
|
+
caution: "Caution",
|
|
261
|
+
refused: "Refused"
|
|
262
|
+
};
|
|
263
|
+
var TONE = {
|
|
264
|
+
live: "success",
|
|
265
|
+
testing: "brand",
|
|
266
|
+
"not-yet": "muted",
|
|
267
|
+
paused: "muted",
|
|
268
|
+
good: "success",
|
|
269
|
+
caution: "brand",
|
|
270
|
+
refused: "danger"
|
|
271
|
+
};
|
|
272
|
+
function statusWord(status) {
|
|
273
|
+
return WORD[status];
|
|
274
|
+
}
|
|
275
|
+
function StatusBadge({ status, className, ...props }) {
|
|
276
|
+
return /* @__PURE__ */ jsx(Badge, { tone: TONE[status], "data-status": status, className: cn(className), ...props, children: WORD[status] });
|
|
277
|
+
}
|
|
253
278
|
var cardVariants = cva("relative rounded-[1.25rem] border", {
|
|
254
279
|
variants: {
|
|
255
280
|
tone: {
|
|
@@ -292,6 +317,20 @@ function CardContent({ className, ...props }) {
|
|
|
292
317
|
function CardFooter({ className, ...props }) {
|
|
293
318
|
return /* @__PURE__ */ jsx("div", { className: cn("mt-6 flex flex-wrap items-center gap-3", className), ...props });
|
|
294
319
|
}
|
|
320
|
+
function sharedContext(name, initial) {
|
|
321
|
+
const key = /* @__PURE__ */ Symbol.for(`@orangecheck/app-design/${name}`);
|
|
322
|
+
const store = globalThis;
|
|
323
|
+
return store[key] ?? (store[key] = createContext(initial));
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// src/lib/density.ts
|
|
327
|
+
var DensityContext = sharedContext("density", "comfortable");
|
|
328
|
+
function DensityProvider({ density, children }) {
|
|
329
|
+
return createElement(DensityContext.Provider, { value: density }, children);
|
|
330
|
+
}
|
|
331
|
+
function useDensity() {
|
|
332
|
+
return useContext(DensityContext);
|
|
333
|
+
}
|
|
295
334
|
var fieldBase = [
|
|
296
335
|
"w-full rounded-xl border border-input bg-card text-foreground placeholder:text-oca-subtle",
|
|
297
336
|
"text-base md:text-[0.9375rem] outline-none transition-[border-color,box-shadow]",
|
|
@@ -299,8 +338,24 @@ var fieldBase = [
|
|
|
299
338
|
"disabled:cursor-not-allowed disabled:opacity-55",
|
|
300
339
|
"aria-[invalid=true]:border-destructive aria-[invalid=true]:focus:ring-[color-mix(in_oklab,var(--destructive)_14%,transparent)]"
|
|
301
340
|
];
|
|
302
|
-
var
|
|
303
|
-
|
|
341
|
+
var FIELD_SIZE = {
|
|
342
|
+
md: "h-11 px-3.5",
|
|
343
|
+
sm: "h-9 rounded-[0.625rem] px-3 md:text-[0.875rem]"
|
|
344
|
+
};
|
|
345
|
+
var Input = forwardRef(function Input2({ className, type = "text", size, ...props }, ref) {
|
|
346
|
+
const density = useDensity();
|
|
347
|
+
const s = size ?? (density === "compact" ? "sm" : "md");
|
|
348
|
+
return /* @__PURE__ */ jsx(
|
|
349
|
+
"input",
|
|
350
|
+
{
|
|
351
|
+
ref,
|
|
352
|
+
type,
|
|
353
|
+
"data-ui": "input",
|
|
354
|
+
"data-size": s,
|
|
355
|
+
className: cn(fieldBase, FIELD_SIZE[s], className),
|
|
356
|
+
...props
|
|
357
|
+
}
|
|
358
|
+
);
|
|
304
359
|
});
|
|
305
360
|
var Textarea = forwardRef(
|
|
306
361
|
function Textarea2({ className, ...props }, ref) {
|
|
@@ -357,15 +412,29 @@ function Field({ label, hint, optional, error, children, className, hideLabel, a
|
|
|
357
412
|
error ? /* @__PURE__ */ jsx("p", { id: errorId, role: "alert", className: "text-[0.8125rem] leading-snug text-destructive", children: error }) : null
|
|
358
413
|
] });
|
|
359
414
|
}
|
|
360
|
-
var
|
|
415
|
+
var SelectFieldContext = sharedContext("select-field", null);
|
|
416
|
+
function Select({
|
|
417
|
+
id,
|
|
418
|
+
"aria-describedby": describedBy,
|
|
419
|
+
"aria-invalid": invalid,
|
|
420
|
+
...props
|
|
421
|
+
}) {
|
|
422
|
+
return /* @__PURE__ */ jsx(SelectFieldContext.Provider, { value: { id, "aria-describedby": describedBy, "aria-invalid": invalid }, children: /* @__PURE__ */ jsx(SelectPrimitive.Root, { ...props }) });
|
|
423
|
+
}
|
|
361
424
|
var SelectGroup = SelectPrimitive.Group;
|
|
362
425
|
var SelectValue = SelectPrimitive.Value;
|
|
363
|
-
var SelectTrigger = forwardRef(function SelectTrigger2({ className, children, ...props }, ref) {
|
|
426
|
+
var SelectTrigger = forwardRef(function SelectTrigger2({ className, children, size, ...props }, ref) {
|
|
427
|
+
const density = useDensity();
|
|
428
|
+
const field = useContext(SelectFieldContext);
|
|
429
|
+
const s = size ?? (density === "compact" ? "sm" : "md");
|
|
364
430
|
return /* @__PURE__ */ jsxs(
|
|
365
431
|
SelectPrimitive.Trigger,
|
|
366
432
|
{
|
|
367
433
|
ref,
|
|
368
|
-
|
|
434
|
+
id: field?.id,
|
|
435
|
+
"aria-describedby": field?.["aria-describedby"],
|
|
436
|
+
"aria-invalid": field?.["aria-invalid"],
|
|
437
|
+
className: cn(fieldBase, FIELD_SIZE[s], "flex items-center justify-between gap-2 text-left", className),
|
|
369
438
|
...props,
|
|
370
439
|
children: [
|
|
371
440
|
/* @__PURE__ */ jsx("span", { className: "truncate", children }),
|
|
@@ -433,7 +502,8 @@ var Switch = forwardRef(function Switch2({ className, ...props }, ref) {
|
|
|
433
502
|
className: cn(
|
|
434
503
|
"peer inline-flex h-6 w-11 shrink-0 items-center rounded-full border border-transparent bg-input p-0.5",
|
|
435
504
|
"outline-none transition-colors focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
436
|
-
|
|
505
|
+
// The deep orange: the track is the state, so it must clear 3:1 on a card.
|
|
506
|
+
"data-[state=checked]:bg-oca-orange-deep disabled:cursor-not-allowed disabled:opacity-50",
|
|
437
507
|
className
|
|
438
508
|
),
|
|
439
509
|
...props,
|
|
@@ -725,7 +795,246 @@ var TabsTrigger = forwardRef(function TabsTrigger2({ className, ...props }, ref)
|
|
|
725
795
|
var TabsContent = forwardRef(function TabsContent2({ className, ...props }, ref) {
|
|
726
796
|
return /* @__PURE__ */ jsx(TabsPrimitive.Content, { ref, className: cn("mt-6 outline-none", className), ...props });
|
|
727
797
|
});
|
|
798
|
+
var GroupName = createContext(void 0);
|
|
799
|
+
function Accordion({
|
|
800
|
+
single = false,
|
|
801
|
+
children,
|
|
802
|
+
className
|
|
803
|
+
}) {
|
|
804
|
+
const name = useId();
|
|
805
|
+
return /* @__PURE__ */ jsx(GroupName.Provider, { value: single ? name : void 0, children: /* @__PURE__ */ jsx("div", { className: cn("divide-y divide-border overflow-hidden rounded-[1.25rem] border border-border bg-card", className), children }) });
|
|
806
|
+
}
|
|
807
|
+
function AccordionItem({
|
|
808
|
+
title,
|
|
809
|
+
children,
|
|
810
|
+
defaultOpen = false,
|
|
811
|
+
id,
|
|
812
|
+
className
|
|
813
|
+
}) {
|
|
814
|
+
const name = useContext(GroupName);
|
|
815
|
+
return /* @__PURE__ */ jsxs("details", { id, name, open: defaultOpen || void 0, className: cn("group scroll-mt-24", className), children: [
|
|
816
|
+
/* @__PURE__ */ jsxs(
|
|
817
|
+
"summary",
|
|
818
|
+
{
|
|
819
|
+
className: cn(
|
|
820
|
+
"flex min-h-14 cursor-pointer list-none items-center justify-between gap-4 px-5 py-4 text-[1rem] font-medium leading-snug md:px-6",
|
|
821
|
+
// Inside the card's clip, so the ring is drawn within the row.
|
|
822
|
+
"transition-colors hover:bg-accent/60 focus-visible:outline-offset-[-2px] [&::-webkit-details-marker]:hidden"
|
|
823
|
+
),
|
|
824
|
+
children: [
|
|
825
|
+
title,
|
|
826
|
+
/* @__PURE__ */ jsx(
|
|
827
|
+
ChevronDown,
|
|
828
|
+
{
|
|
829
|
+
"aria-hidden": true,
|
|
830
|
+
className: "size-4 shrink-0 text-muted-foreground transition-transform duration-200 group-open:rotate-180"
|
|
831
|
+
}
|
|
832
|
+
)
|
|
833
|
+
]
|
|
834
|
+
}
|
|
835
|
+
),
|
|
836
|
+
/* @__PURE__ */ jsx("div", { className: "oca-body px-5 pb-5 text-[0.9375rem] md:px-6 md:pb-6", children })
|
|
837
|
+
] });
|
|
838
|
+
}
|
|
839
|
+
var queue = [];
|
|
840
|
+
var asked = 0;
|
|
841
|
+
var hosts = 0;
|
|
842
|
+
var listeners = /* @__PURE__ */ new Set();
|
|
843
|
+
var emit = () => listeners.forEach((l) => l());
|
|
844
|
+
function ask(item) {
|
|
845
|
+
queue = [...queue, { ...item, id: ++asked }];
|
|
846
|
+
emit();
|
|
847
|
+
}
|
|
848
|
+
function done() {
|
|
849
|
+
queue = queue.slice(1);
|
|
850
|
+
emit();
|
|
851
|
+
}
|
|
852
|
+
function confirm(options) {
|
|
853
|
+
if (hosts === 0) {
|
|
854
|
+
console.error("confirm(): no <DialogHost /> is mounted, so nothing was asked; treating it as no.");
|
|
855
|
+
return Promise.resolve(false);
|
|
856
|
+
}
|
|
857
|
+
return new Promise((resolve) => ask({ id: 0, kind: "confirm", options, settle: resolve }));
|
|
858
|
+
}
|
|
859
|
+
function prompt(options) {
|
|
860
|
+
if (hosts === 0) {
|
|
861
|
+
console.error("prompt(): no <DialogHost /> is mounted, so nothing was asked; treating it as cancelled.");
|
|
862
|
+
return Promise.resolve(null);
|
|
863
|
+
}
|
|
864
|
+
return new Promise((resolve) => ask({ id: 0, kind: "prompt", options, settle: resolve }));
|
|
865
|
+
}
|
|
866
|
+
function subscribe(listener) {
|
|
867
|
+
listeners.add(listener);
|
|
868
|
+
hosts++;
|
|
869
|
+
return () => {
|
|
870
|
+
listeners.delete(listener);
|
|
871
|
+
hosts--;
|
|
872
|
+
};
|
|
873
|
+
}
|
|
874
|
+
var current = () => queue[0] ?? null;
|
|
875
|
+
var none = () => null;
|
|
876
|
+
function PromptBody({ ask: a }) {
|
|
877
|
+
const o = a.options;
|
|
878
|
+
const [value, setValue] = useState(o.defaultValue ?? "");
|
|
879
|
+
const [error, setError] = useState(null);
|
|
880
|
+
const submit = (e) => {
|
|
881
|
+
e.preventDefault();
|
|
882
|
+
if (o.minLength && value.length < o.minLength) {
|
|
883
|
+
setError(`At least ${o.minLength} characters.`);
|
|
884
|
+
return;
|
|
885
|
+
}
|
|
886
|
+
const refused = o.validate?.(value);
|
|
887
|
+
if (refused) {
|
|
888
|
+
setError(refused);
|
|
889
|
+
return;
|
|
890
|
+
}
|
|
891
|
+
a.settle(value);
|
|
892
|
+
done();
|
|
893
|
+
};
|
|
894
|
+
return /* @__PURE__ */ jsxs("form", { onSubmit: submit, noValidate: true, children: [
|
|
895
|
+
/* @__PURE__ */ jsx(Field, { label: o.label ?? "Your answer", hint: o.hint, error, children: /* @__PURE__ */ jsx(
|
|
896
|
+
Input,
|
|
897
|
+
{
|
|
898
|
+
autoFocus: true,
|
|
899
|
+
type: o.secret ? "password" : "text",
|
|
900
|
+
autoComplete: o.secret ? "new-password" : "off",
|
|
901
|
+
placeholder: o.placeholder,
|
|
902
|
+
value,
|
|
903
|
+
onChange: (e) => {
|
|
904
|
+
setValue(e.target.value);
|
|
905
|
+
setError(null);
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
) }),
|
|
909
|
+
/* @__PURE__ */ jsxs(DialogFooter, { children: [
|
|
910
|
+
/* @__PURE__ */ jsx(
|
|
911
|
+
Button,
|
|
912
|
+
{
|
|
913
|
+
variant: "secondary",
|
|
914
|
+
onClick: () => {
|
|
915
|
+
a.settle(null);
|
|
916
|
+
done();
|
|
917
|
+
},
|
|
918
|
+
children: o.cancelLabel ?? "Cancel"
|
|
919
|
+
}
|
|
920
|
+
),
|
|
921
|
+
/* @__PURE__ */ jsx(Button, { type: "submit", variant: o.destructive ? "danger" : "primary", children: o.confirmLabel ?? "Continue" })
|
|
922
|
+
] })
|
|
923
|
+
] });
|
|
924
|
+
}
|
|
925
|
+
function DialogHost() {
|
|
926
|
+
const a = useSyncExternalStore(subscribe, current, none);
|
|
927
|
+
const cancel = () => {
|
|
928
|
+
if (!a) return;
|
|
929
|
+
if (a.kind === "confirm") a.settle(false);
|
|
930
|
+
else a.settle(null);
|
|
931
|
+
done();
|
|
932
|
+
};
|
|
933
|
+
return /* @__PURE__ */ jsx(Dialog, { open: a !== null, onOpenChange: (open) => open ? void 0 : cancel(), children: a ? /* @__PURE__ */ jsxs(
|
|
934
|
+
DialogContent,
|
|
935
|
+
{
|
|
936
|
+
role: "alertdialog",
|
|
937
|
+
...a.options.message ? {} : { "aria-describedby": void 0 },
|
|
938
|
+
className: "w-[min(92vw,28rem)]",
|
|
939
|
+
children: [
|
|
940
|
+
/* @__PURE__ */ jsxs(DialogHeader, { children: [
|
|
941
|
+
/* @__PURE__ */ jsx(DialogTitle, { children: a.options.title }),
|
|
942
|
+
a.options.message ? /* @__PURE__ */ jsx(DialogDescription, { children: a.options.message }) : null
|
|
943
|
+
] }),
|
|
944
|
+
a.kind === "prompt" ? (
|
|
945
|
+
// Keyed by the ask, so a second prompt starts empty.
|
|
946
|
+
/* @__PURE__ */ jsx(PromptBody, { ask: a }, a.id)
|
|
947
|
+
) : /* @__PURE__ */ jsxs(DialogFooter, { children: [
|
|
948
|
+
/* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: cancel, children: a.options.cancelLabel ?? "Cancel" }),
|
|
949
|
+
/* @__PURE__ */ jsx(
|
|
950
|
+
Button,
|
|
951
|
+
{
|
|
952
|
+
variant: a.options.destructive ? "danger" : "primary",
|
|
953
|
+
onClick: () => {
|
|
954
|
+
a.settle(true);
|
|
955
|
+
done();
|
|
956
|
+
},
|
|
957
|
+
children: a.options.confirmLabel ?? "Continue"
|
|
958
|
+
}
|
|
959
|
+
)
|
|
960
|
+
] })
|
|
961
|
+
]
|
|
962
|
+
}
|
|
963
|
+
) : null });
|
|
964
|
+
}
|
|
965
|
+
var N = new Intl.NumberFormat("en-US");
|
|
966
|
+
function Pagination({
|
|
967
|
+
pageIndex,
|
|
968
|
+
pageSize,
|
|
969
|
+
total,
|
|
970
|
+
onPage,
|
|
971
|
+
label = "Pages",
|
|
972
|
+
className
|
|
973
|
+
}) {
|
|
974
|
+
const pages = Math.max(1, Math.ceil(total / pageSize));
|
|
975
|
+
const index = Math.min(Math.max(0, pageIndex), pages - 1);
|
|
976
|
+
if (index !== pageIndex && typeof process !== "undefined" && process.env.NODE_ENV !== "production") {
|
|
977
|
+
console.warn(`Pagination: pageIndex ${pageIndex} is outside 0\u2013${pages - 1}; it counts from 0.`);
|
|
978
|
+
}
|
|
979
|
+
if (total <= pageSize) return null;
|
|
980
|
+
const from = index * pageSize + 1;
|
|
981
|
+
const to = Math.min(total, (index + 1) * pageSize);
|
|
982
|
+
return /* @__PURE__ */ jsxs("nav", { "aria-label": label, className: cn("flex items-center justify-between gap-4", className), children: [
|
|
983
|
+
/* @__PURE__ */ jsxs("p", { "aria-live": "polite", className: "oca-tabular text-[0.875rem] text-muted-foreground", children: [
|
|
984
|
+
N.format(from),
|
|
985
|
+
"\u2013",
|
|
986
|
+
N.format(to),
|
|
987
|
+
" of ",
|
|
988
|
+
N.format(total)
|
|
989
|
+
] }),
|
|
990
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
991
|
+
/* @__PURE__ */ jsxs(Button, { variant: "secondary", size: "sm", disabled: index === 0, onClick: () => onPage(index - 1), className: "pl-3", children: [
|
|
992
|
+
/* @__PURE__ */ jsx(ChevronLeft, { "aria-hidden": true }),
|
|
993
|
+
"Previous"
|
|
994
|
+
] }),
|
|
995
|
+
/* @__PURE__ */ jsxs(Button, { variant: "secondary", size: "sm", disabled: index >= pages - 1, onClick: () => onPage(index + 1), className: "pr-3", children: [
|
|
996
|
+
"Next",
|
|
997
|
+
/* @__PURE__ */ jsx(ChevronRight, { "aria-hidden": true })
|
|
998
|
+
] })
|
|
999
|
+
] })
|
|
1000
|
+
] });
|
|
1001
|
+
}
|
|
1002
|
+
function QrCode({
|
|
1003
|
+
value,
|
|
1004
|
+
size = 200,
|
|
1005
|
+
label,
|
|
1006
|
+
className
|
|
1007
|
+
}) {
|
|
1008
|
+
const matrix = useMemo(() => {
|
|
1009
|
+
try {
|
|
1010
|
+
return QRCode.create(value, { errorCorrectionLevel: "M" }).modules;
|
|
1011
|
+
} catch {
|
|
1012
|
+
return null;
|
|
1013
|
+
}
|
|
1014
|
+
}, [value]);
|
|
1015
|
+
const path = useMemo(() => {
|
|
1016
|
+
if (!matrix) return "";
|
|
1017
|
+
let d = "";
|
|
1018
|
+
for (let y = 0; y < matrix.size; y++) {
|
|
1019
|
+
for (let x = 0; x < matrix.size; x++) {
|
|
1020
|
+
if (matrix.get(y, x)) d += `M${x} ${y}h1v1h-1z`;
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
return d;
|
|
1024
|
+
}, [matrix]);
|
|
1025
|
+
const short = value.length > 28 ? `${value.slice(0, 28)}\u2026` : value;
|
|
1026
|
+
return /* @__PURE__ */ jsx(
|
|
1027
|
+
"div",
|
|
1028
|
+
{
|
|
1029
|
+
role: "img",
|
|
1030
|
+
"aria-label": matrix ? label ?? `QR code for ${short}` : "Too long for a QR code",
|
|
1031
|
+
className: cn("inline-block shrink-0 rounded-2xl bg-white p-3 ring-1 ring-border", className),
|
|
1032
|
+
style: { width: size, height: size },
|
|
1033
|
+
children: matrix ? /* @__PURE__ */ jsx("svg", { viewBox: `0 0 ${matrix.size} ${matrix.size}`, shapeRendering: "crispEdges", "aria-hidden": true, className: "block size-full", children: /* @__PURE__ */ jsx("path", { d: path, fill: "#0a0a0a" }) }) : /* @__PURE__ */ jsx("div", { "aria-hidden": true, className: "flex size-full items-center justify-center text-center text-[0.8125rem] text-[#54585e]", children: "Too long for a QR code" })
|
|
1034
|
+
}
|
|
1035
|
+
);
|
|
1036
|
+
}
|
|
728
1037
|
|
|
729
|
-
export { Badge, Button, Card, CardContent, CardDescription, CardFooter, CardHeader, CardNumeral, CardTitle, Checkbox, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, Field, Input, Kbd, Label, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, RadioGroup, RadioGroupItem, ScrollFade, Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue, Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetTitle, SheetTrigger, Skeleton, Spinner, StatusDot, StatusPill, Switch, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, Toaster, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, badgeVariants, buttonVariants, cardVariants, cn, useTimedOut };
|
|
1038
|
+
export { Accordion, AccordionItem, Badge, Button, Card, CardContent, CardDescription, CardFooter, CardHeader, CardNumeral, CardTitle, Checkbox, DensityProvider, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogHost, DialogTitle, DialogTrigger, DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, Field, Input, Kbd, Label, Pagination, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, QrCode, RadioGroup, RadioGroupItem, ScrollFade, Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue, Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetTitle, SheetTrigger, Skeleton, Spinner, StatusBadge, StatusDot, StatusPill, Switch, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, Toaster, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, badgeVariants, buttonVariants, cardVariants, cn, confirm, prompt, statusWord, useDensity, useTimedOut };
|
|
730
1039
|
//# sourceMappingURL=primitives.mjs.map
|
|
731
1040
|
//# sourceMappingURL=primitives.mjs.map
|