@nim.zone/ui 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +681 -0
  3. package/dist/components/admin-shell.d.ts +121 -0
  4. package/dist/components/app-shell.d.ts +23 -0
  5. package/dist/components/auth-screen.d.ts +33 -0
  6. package/dist/components/avatar.d.ts +10 -0
  7. package/dist/components/badge.d.ts +14 -0
  8. package/dist/components/banner.d.ts +11 -0
  9. package/dist/components/breadcrumb.d.ts +12 -0
  10. package/dist/components/button.d.ts +21 -0
  11. package/dist/components/card.d.ts +15 -0
  12. package/dist/components/chat-composer.d.ts +52 -0
  13. package/dist/components/chat.d.ts +77 -0
  14. package/dist/components/checkout.d.ts +79 -0
  15. package/dist/components/choice.d.ts +15 -0
  16. package/dist/components/combobox.d.ts +31 -0
  17. package/dist/components/date-field.d.ts +58 -0
  18. package/dist/components/dialog.d.ts +20 -0
  19. package/dist/components/empty-state.d.ts +9 -0
  20. package/dist/components/feedback.d.ts +18 -0
  21. package/dist/components/field.d.ts +47 -0
  22. package/dist/components/icon-button.d.ts +12 -0
  23. package/dist/components/icon.d.ts +72 -0
  24. package/dist/components/layout.d.ts +13 -0
  25. package/dist/components/list.d.ts +16 -0
  26. package/dist/components/menu.d.ts +56 -0
  27. package/dist/components/onboarding.d.ts +50 -0
  28. package/dist/components/otp-input.d.ts +29 -0
  29. package/dist/components/pagination.d.ts +12 -0
  30. package/dist/components/password-field.d.ts +33 -0
  31. package/dist/components/phone-field.d.ts +44 -0
  32. package/dist/components/plan-card.d.ts +45 -0
  33. package/dist/components/plan-picker.d.ts +52 -0
  34. package/dist/components/profile-header.d.ts +47 -0
  35. package/dist/components/profile-screen.d.ts +44 -0
  36. package/dist/components/resource-meter.d.ts +22 -0
  37. package/dist/components/section-header.d.ts +8 -0
  38. package/dist/components/segmented.d.ts +18 -0
  39. package/dist/components/sheet.d.ts +18 -0
  40. package/dist/components/sign-in-flow.d.ts +60 -0
  41. package/dist/components/slider.d.ts +10 -0
  42. package/dist/components/stat.d.ts +10 -0
  43. package/dist/components/stepper.d.ts +17 -0
  44. package/dist/components/tab-bar.d.ts +40 -0
  45. package/dist/components/table.d.ts +33 -0
  46. package/dist/components/tabs.d.ts +23 -0
  47. package/dist/components/task-progress.d.ts +38 -0
  48. package/dist/components/theme.d.ts +49 -0
  49. package/dist/components/toast.d.ts +17 -0
  50. package/dist/components/tooltip.d.ts +18 -0
  51. package/dist/components/typography.d.ts +18 -0
  52. package/dist/components/wizard.d.ts +70 -0
  53. package/dist/index.d.ts +104 -0
  54. package/dist/lib/calendars.d.ts +81 -0
  55. package/dist/lib/cn.d.ts +7 -0
  56. package/dist/lib/countries.d.ts +33 -0
  57. package/dist/lib/use-anchor.d.ts +22 -0
  58. package/dist/nim.css +1 -0
  59. package/dist/nim.js +3266 -0
  60. package/package.json +83 -0
  61. package/src/components/admin-shell.tsx +338 -0
  62. package/src/components/app-shell.tsx +36 -0
  63. package/src/components/auth-screen.tsx +71 -0
  64. package/src/components/avatar.tsx +32 -0
  65. package/src/components/badge.tsx +44 -0
  66. package/src/components/banner.tsx +47 -0
  67. package/src/components/breadcrumb.tsx +45 -0
  68. package/src/components/button.tsx +64 -0
  69. package/src/components/card.tsx +46 -0
  70. package/src/components/chat-composer.tsx +331 -0
  71. package/src/components/chat.tsx +352 -0
  72. package/src/components/checkout.tsx +173 -0
  73. package/src/components/choice.tsx +46 -0
  74. package/src/components/combobox.tsx +157 -0
  75. package/src/components/date-field.tsx +394 -0
  76. package/src/components/dialog.tsx +77 -0
  77. package/src/components/empty-state.tsx +23 -0
  78. package/src/components/feedback.tsx +61 -0
  79. package/src/components/field.tsx +177 -0
  80. package/src/components/icon-button.tsx +35 -0
  81. package/src/components/icon.tsx +167 -0
  82. package/src/components/layout.tsx +38 -0
  83. package/src/components/list.tsx +78 -0
  84. package/src/components/menu.tsx +172 -0
  85. package/src/components/onboarding.tsx +157 -0
  86. package/src/components/otp-input.tsx +144 -0
  87. package/src/components/pagination.tsx +86 -0
  88. package/src/components/password-field.tsx +112 -0
  89. package/src/components/phone-field.tsx +242 -0
  90. package/src/components/plan-card.tsx +124 -0
  91. package/src/components/plan-picker.tsx +144 -0
  92. package/src/components/profile-header.tsx +134 -0
  93. package/src/components/profile-screen.tsx +104 -0
  94. package/src/components/resource-meter.tsx +60 -0
  95. package/src/components/section-header.tsx +31 -0
  96. package/src/components/segmented.tsx +53 -0
  97. package/src/components/sheet.tsx +74 -0
  98. package/src/components/sign-in-flow.tsx +322 -0
  99. package/src/components/slider.tsx +50 -0
  100. package/src/components/stat.tsx +30 -0
  101. package/src/components/stepper.tsx +77 -0
  102. package/src/components/tab-bar.tsx +82 -0
  103. package/src/components/table.tsx +81 -0
  104. package/src/components/tabs.tsx +72 -0
  105. package/src/components/task-progress.tsx +111 -0
  106. package/src/components/theme.tsx +112 -0
  107. package/src/components/toast.tsx +87 -0
  108. package/src/components/tooltip.tsx +30 -0
  109. package/src/components/typography.tsx +65 -0
  110. package/src/components/wizard.tsx +192 -0
  111. package/src/index.ts +216 -0
  112. package/src/lib/calendars.ts +227 -0
  113. package/src/lib/cn.ts +8 -0
  114. package/src/lib/countries.ts +110 -0
  115. package/src/lib/use-anchor.ts +92 -0
  116. package/src/theme/colorways/coral.css +62 -0
  117. package/src/theme/colorways/oxblood.css +23 -0
  118. package/src/theme/colorways/paper.css +68 -0
  119. package/src/theme/colorways/teal.css +56 -0
  120. package/src/theme/colorways/vermilion.css +21 -0
  121. package/src/theme/components.css +4606 -0
  122. package/src/theme/contract.css +204 -0
  123. package/src/theme/fonts.css +67 -0
  124. package/src/theme/index.css +33 -0
  125. package/src/theme/persian.css +47 -0
  126. package/src/theme/reset.css +118 -0
  127. package/src/theme/styles/ledger.css +106 -0
  128. package/src/theme/styles/vlora.css +91 -0
  129. package/src/vite-env.d.ts +1 -0
@@ -0,0 +1,18 @@
1
+ import { ReactNode } from 'react';
2
+ export interface SheetProps {
3
+ children: ReactNode;
4
+ className?: string;
5
+ /** Label for the close control; also names the dialog when no title is set. */
6
+ closeLabel?: string;
7
+ footer?: ReactNode;
8
+ onClose: () => void;
9
+ open: boolean;
10
+ title?: ReactNode;
11
+ }
12
+ /**
13
+ * The bottom sheet is nim's modal surface. It owns the three things that are
14
+ * always forgotten in hand-rolled sheets: the page behind it must not scroll,
15
+ * Escape must close it, and focus must move into it on open and be restorable
16
+ * on close.
17
+ */
18
+ export declare function Sheet({ children, className, closeLabel, footer, onClose, open, title }: SheetProps): import('react').ReactPortal | null;
@@ -0,0 +1,60 @@
1
+ import { ReactNode } from 'react';
2
+ export type SignInMethod = 'code' | 'password';
3
+ export interface SignInCopy {
4
+ back: string;
5
+ codeLabel: string;
6
+ codeSubtitle: (destination: string) => ReactNode;
7
+ codeTitle: string;
8
+ identifierLabel: string;
9
+ passwordLabel: string;
10
+ passwordSubtitle: ReactNode;
11
+ passwordTitle: string;
12
+ phoneLabel: string;
13
+ phoneSubtitle: ReactNode;
14
+ phoneTitle: string;
15
+ resend: string;
16
+ resendIn: (seconds: number) => string;
17
+ sendCode: string;
18
+ signIn: string;
19
+ usePassword: string;
20
+ usePhone: string;
21
+ verify: string;
22
+ }
23
+ export interface SignInFlowProps {
24
+ brand?: ReactNode;
25
+ className?: string;
26
+ codeLength?: number;
27
+ copy?: Partial<SignInCopy>;
28
+ /** ISO 3166-1 alpha-2 the phone step opens on. */
29
+ defaultCountry?: string;
30
+ /** Which door the flow opens on. With both methods enabled the viewer can
31
+ switch; with one, the other is never offered. */
32
+ defaultMethod?: SignInMethod;
33
+ /** Terms line, support link — under the action on every step. */
34
+ footer?: ReactNode;
35
+ methods?: SignInMethod[];
36
+ /** Ask the backend for a code. Rejecting shows the message on the step. */
37
+ onRequestCode?: (e164: string) => Promise<void> | void;
38
+ /** Verify it. Resolving is success — routing afterwards is the caller's. */
39
+ onVerifyCode?: (e164: string, code: string) => Promise<void> | void;
40
+ onPasswordSignIn?: (identifier: string, password: string) => Promise<void> | void;
41
+ /** Countries floated to the top of the picker. */
42
+ priority?: string[];
43
+ /** Seconds before "send it again" is offered. */
44
+ resendSeconds?: number;
45
+ }
46
+ /**
47
+ * The whole sign-in, ready to mount: phone → code, or email → password, with
48
+ * the resend countdown, the loading and error states, and the step machine
49
+ * already wired.
50
+ *
51
+ * The caller supplies three async functions and gets a working screen. Nothing
52
+ * here knows about a router or an API client — `onVerifyCode` resolving *is*
53
+ * success, and where the viewer goes next is the app's decision, made in one
54
+ * place instead of at each of the flow's five exits.
55
+ *
56
+ * Compose `AuthScreen`, `PhoneField`, `OtpInput` and `PasswordField` by hand
57
+ * instead when the product's flow differs — an invite code step, a captcha, a
58
+ * tenant picker. This is the common shape, not the only one.
59
+ */
60
+ export declare function SignInFlow({ brand, className, codeLength, copy, defaultCountry, defaultMethod, footer, methods, onPasswordSignIn, onRequestCode, onVerifyCode, priority, resendSeconds, }: SignInFlowProps): import("react").JSX.Element;
@@ -0,0 +1,10 @@
1
+ import { InputHTMLAttributes } from 'react';
2
+ export interface SliderProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'type'> {
3
+ label?: string;
4
+ max?: number;
5
+ min?: number;
6
+ /** Rendered beneath the track, evenly spaced — e.g. ['1M', '8M', '15M']. */
7
+ scale?: string[];
8
+ value: number;
9
+ }
10
+ export declare function Slider({ className, label, max, min, scale, step, value, ...props }: SliderProps): import("react").JSX.Element;
@@ -0,0 +1,10 @@
1
+ import { HTMLAttributes, ReactNode } from 'react';
2
+ export interface StatProps extends HTMLAttributes<HTMLDivElement> {
3
+ /** Signed change, e.g. `+12%`. Direction colours it and picks the arrow. */
4
+ delta?: string;
5
+ deltaDirection?: 'down' | 'up';
6
+ label: ReactNode;
7
+ unit?: ReactNode;
8
+ value: ReactNode;
9
+ }
10
+ export declare function Stat({ className, delta, deltaDirection, label, unit, value, ...props }: StatProps): import("react").JSX.Element;
@@ -0,0 +1,17 @@
1
+ export interface StepperProps {
2
+ className?: string;
3
+ decrementLabel?: string;
4
+ incrementLabel?: string;
5
+ label: string;
6
+ max?: number;
7
+ min?: number;
8
+ onChange: (value: number) => void;
9
+ step?: number;
10
+ value: number;
11
+ }
12
+ /**
13
+ * A number with two full-size targets. Both buttons are control-height
14
+ * squares, so the pair clears the touch minimum rather than shrinking into the
15
+ * cramped ± chevrons this control usually becomes.
16
+ */
17
+ export declare function Stepper({ className, decrementLabel, incrementLabel, label, max, min, onChange, step, value, }: StepperProps): import("react").JSX.Element;
@@ -0,0 +1,40 @@
1
+ import { ReactNode } from 'react';
2
+ import { IconName } from './icon';
3
+ export interface TabBarItem {
4
+ /** Lifted and filled: the one action the product is for. At most one item
5
+ should carry it — two centres is no centre. */
6
+ center?: boolean;
7
+ href?: string;
8
+ icon: IconName;
9
+ /** Full name for assistive tech when `label` is shortened to fit. */
10
+ fullLabel?: string;
11
+ key: string;
12
+ label: string;
13
+ onSelect?: () => void;
14
+ }
15
+ export interface TabBarProps {
16
+ /** Accessible name for the bar itself. */
17
+ label: string;
18
+ className?: string;
19
+ items: TabBarItem[];
20
+ /** `key` of the active item. */
21
+ value: string;
22
+ /** Wrap items in the app's own router link. Given the item and the rendered
23
+ content, returns the element to use — nim never imports a router. */
24
+ renderItem?: (item: TabBarItem, content: ReactNode, props: Record<string, unknown>) => ReactNode;
25
+ }
26
+ /**
27
+ * The floating bottom navigation of a mobile app: three to five destinations,
28
+ * one of them optionally lifted into a primary action.
29
+ *
30
+ * It renders real links or buttons and marks the active one with
31
+ * `aria-current="page"`, so the bar is navigable by keyboard and readable by
32
+ * assistive tech. Routing stays outside: `renderItem` hands the caller the
33
+ * content and the props to spread onto their own `<Link>`, which is why the
34
+ * kit ships no router dependency.
35
+ *
36
+ * It sits above the safe-area inset rather than under the home indicator, and
37
+ * the page below owes it `padding-block-end` — a bar that covers the last row
38
+ * of a list is the most common way this pattern goes wrong.
39
+ */
40
+ export declare function TabBar({ className, items, label, renderItem, value }: TabBarProps): import("react").JSX.Element;
@@ -0,0 +1,33 @@
1
+ import { ReactNode } from 'react';
2
+ export type SortDirection = 'ascending' | 'descending';
3
+ export interface TableColumn<Row> {
4
+ /** Aligns to the trailing edge in tabular figures. Use it for money, counts,
5
+ and dates — anything a reader compares down a column. */
6
+ numeric?: boolean;
7
+ header: ReactNode;
8
+ key: string;
9
+ render: (row: Row) => ReactNode;
10
+ sortable?: boolean;
11
+ width?: string;
12
+ }
13
+ export interface TableProps<Row> {
14
+ caption?: string;
15
+ className?: string;
16
+ columns: TableColumn<Row>[];
17
+ onSort?: (key: string) => void;
18
+ rowKey: (row: Row) => string;
19
+ rows: Row[];
20
+ sort?: {
21
+ direction: SortDirection;
22
+ key: string;
23
+ };
24
+ }
25
+ /**
26
+ * A table, not a grid of divs: the caller supplies columns and rows and gets
27
+ * real `<table>` semantics, which is what lets a screen reader announce "row 3
28
+ * of 84, Amount 4,200".
29
+ *
30
+ * Row height follows `--nim-density`, the same multiplier that drives control
31
+ * heights — the reason density is a token rather than a prop here.
32
+ */
33
+ export declare function Table<Row>({ caption, className, columns, onSort, rowKey, rows, sort }: TableProps<Row>): import("react").JSX.Element;
@@ -0,0 +1,23 @@
1
+ import { HTMLAttributes } from 'react';
2
+ export interface TabOption<T extends string> {
3
+ /** A trailing figure — a count, never a decoration. */
4
+ count?: number | string;
5
+ disabled?: boolean;
6
+ label: string;
7
+ value: T;
8
+ }
9
+ export interface TabsProps<T extends string> extends Omit<HTMLAttributes<HTMLDivElement>, 'onChange'> {
10
+ label: string;
11
+ onChange: (value: T) => void;
12
+ options: TabOption<T>[];
13
+ value: T;
14
+ }
15
+ /**
16
+ * Tabs switch a region of the page. A Segmented control sets a value. They
17
+ * look similar and mean different things, and 0.1 had the segmented control
18
+ * carrying both jobs.
19
+ *
20
+ * Arrow keys move between tabs and select as they go — the pattern a tablist
21
+ * is expected to follow when its panels are cheap to render.
22
+ */
23
+ export declare function Tabs<T extends string>({ className, label, onChange, options, value, ...props }: TabsProps<T>): import("react").JSX.Element;
@@ -0,0 +1,38 @@
1
+ import { ReactNode } from 'react';
2
+ export type TaskStepStatus = 'active' | 'done' | 'failed' | 'pending' | 'skipped';
3
+ export interface TaskStep {
4
+ /** What went wrong, or what is happening. Shown under the label — a status
5
+ word alone leaves a stuck viewer with nothing to act on. */
6
+ detail?: ReactNode;
7
+ id: string;
8
+ label: ReactNode;
9
+ status: TaskStepStatus;
10
+ }
11
+ export interface TaskProgressProps {
12
+ /** Rendered under the steps: a cancel control, a support line. */
13
+ action?: ReactNode;
14
+ className?: string;
15
+ /** The headline under the ring — what the job is doing right now. */
16
+ caption?: ReactNode;
17
+ labels?: {
18
+ of: (done: number, total: number) => string;
19
+ status: Record<TaskStepStatus, string>;
20
+ };
21
+ steps: TaskStep[];
22
+ title?: ReactNode;
23
+ /** 0–100. Omit to derive it from the steps, which is what a job with equal
24
+ stages wants; pass it when the server knows better. */
25
+ value?: number;
26
+ }
27
+ /**
28
+ * A long-running job the viewer is waiting on: a scan, an import, a render.
29
+ *
30
+ * The steps are the point. A bare percentage tells someone how long to wait;
31
+ * a named stage tells them what is happening and, when it fails, which part
32
+ * failed — which is the difference between "try again" and "try again with a
33
+ * better photo". Failure is a state of a step, not a replacement for the list.
34
+ *
35
+ * The region is `aria-live="polite"`, so a stage completing is announced
36
+ * without the viewer having to keep looking at it.
37
+ */
38
+ export declare function TaskProgress({ action, caption, className, labels, steps, title, value, }: TaskProgressProps): import("react").JSX.Element;
@@ -0,0 +1,49 @@
1
+ import { ReactNode } from 'react';
2
+ /**
3
+ * nim has two independent appearance axes.
4
+ *
5
+ * A STYLE owns how the interface is shaped: radii, elevation geometry, type
6
+ * voice, press behaviour. A COLOURWAY owns how it is coloured: surfaces, ink,
7
+ * lines, accent, status. They compose freely — `ledger` + `teal` is a legal
8
+ * pairing, not a mistake — which is why they are two attributes rather than
9
+ * one `theme` name multiplying out into a file per combination.
10
+ */
11
+ export type NimStyle = 'ledger' | 'vlora';
12
+ export type NimColorway = 'coral' | 'oxblood' | 'teal' | 'vermilion';
13
+ /** `system` follows the OS and is resolved by CSS, not by JavaScript. */
14
+ export type NimScheme = 'dark' | 'light' | 'system';
15
+ export type NimDirection = 'ltr' | 'rtl';
16
+ interface NimContextValue {
17
+ colorway: NimColorway;
18
+ direction: NimDirection;
19
+ /** BCP 47 tag. Components that format dates or numbers use it; the script
20
+ corrections in `persian.css` key off the `lang` attribute it writes. */
21
+ locale: string | undefined;
22
+ scheme: NimScheme;
23
+ setColorway: (colorway: NimColorway) => void;
24
+ setScheme: (scheme: NimScheme) => void;
25
+ setStyle: (style: NimStyle) => void;
26
+ style: NimStyle;
27
+ }
28
+ export interface NimProviderProps {
29
+ children: ReactNode;
30
+ className?: string;
31
+ defaultColorway?: NimColorway;
32
+ defaultScheme?: NimScheme;
33
+ defaultStyle?: NimStyle;
34
+ direction?: NimDirection;
35
+ /** BCP 47 tag, e.g. `fa-IR`. Written to `lang`, which is what turns on the
36
+ Persian script corrections and gives Calendar its month and weekday
37
+ names and its digits. Direction is separate: `dir` says which way the
38
+ line runs, `lang` says which script is being set. */
39
+ locale?: string;
40
+ /** Writes the appearance attributes onto <html> as well, so portalled
41
+ surfaces (sheets, dialogs, menus, toasts) inherit them from outside the
42
+ React tree. */
43
+ syncDocument?: boolean;
44
+ }
45
+ export declare function NimProvider({ children, className, defaultColorway, defaultScheme, defaultStyle, direction, locale, syncDocument, }: NimProviderProps): import("react").JSX.Element;
46
+ export declare function useNim(): NimContextValue;
47
+ /** Convenience for a header toggle: flips light ⇄ dark, leaving `system`. */
48
+ export declare function useSchemeToggle(): () => void;
49
+ export {};
@@ -0,0 +1,17 @@
1
+ import { ReactNode } from 'react';
2
+ export type ToastTone = 'accent' | 'danger' | 'neutral' | 'success';
3
+ export interface ToastOptions {
4
+ action?: {
5
+ label: string;
6
+ onPress: () => void;
7
+ };
8
+ /** Milliseconds on screen. Pass 0 to require a manual dismissal. */
9
+ duration?: number;
10
+ message: string;
11
+ tone?: ToastTone;
12
+ }
13
+ export declare function ToastProvider({ children }: {
14
+ children: ReactNode;
15
+ }): import("react").JSX.Element;
16
+ /** Throws when used outside the provider — a silent no-op would hide the bug. */
17
+ export declare function useToast(): (options: ToastOptions) => void;
@@ -0,0 +1,18 @@
1
+ import { ReactNode } from 'react';
2
+ export interface TooltipProps {
3
+ children: ReactNode;
4
+ className?: string;
5
+ /** The text shown on hover. Never the only place the name lives. */
6
+ label: string;
7
+ }
8
+ /**
9
+ * A name for a control that shows only an icon.
10
+ *
11
+ * The bubble is `aria-hidden`: the trigger inside must already carry its own
12
+ * accessible name (IconButton does), so a screen reader is never read the same
13
+ * label twice, and a viewer who cannot hover never depends on this.
14
+ *
15
+ * Hover waits 200ms; keyboard focus does not, because a viewer who tabbed here
16
+ * has already asked.
17
+ */
18
+ export declare function Tooltip({ children, className, label }: TooltipProps): import("react").JSX.Element;
@@ -0,0 +1,18 @@
1
+ import { ElementType, HTMLAttributes, ReactNode } from 'react';
2
+ interface TextProps extends HTMLAttributes<HTMLElement> {
3
+ as?: ElementType;
4
+ children: ReactNode;
5
+ }
6
+ /** The largest role: page-opening statements only, one per screen. */
7
+ export declare function Display({ as: Component, children, className, ...props }: TextProps): import("react").JSX.Element;
8
+ export declare function Title({ as: Component, children, className, size, ...props }: TextProps & {
9
+ size?: 'lg' | 'md';
10
+ }): import("react").JSX.Element;
11
+ export declare function Body({ as: Component, children, className, size, ...props }: TextProps & {
12
+ size?: 'md' | 'sm';
13
+ }): import("react").JSX.Element;
14
+ /** Mono/uppercase in Ledger, sentence case in Vlora — the theme decides. */
15
+ export declare function Label({ as: Component, children, className, ...props }: TextProps): import("react").JSX.Element;
16
+ export declare function Caption({ as: Component, children, className, ...props }: TextProps): import("react").JSX.Element;
17
+ export declare function Rule({ className, ...props }: HTMLAttributes<HTMLHRElement>): import("react").JSX.Element;
18
+ export {};
@@ -0,0 +1,70 @@
1
+ import { ReactNode } from 'react';
2
+ export interface WizardStep {
3
+ /** The step itself. A function receives nothing — the caller already holds
4
+ the answers, because they are the app's, not the wizard's. */
5
+ content: ReactNode;
6
+ /** Blocks the CTA until the step is answered. */
7
+ canContinue?: boolean;
8
+ /** Overrides the CTA label on this step alone. */
9
+ continueLabel?: string;
10
+ id: string;
11
+ /** The one thing being asked. Kept short: a wizard step is a question. */
12
+ question?: ReactNode;
13
+ subtitle?: ReactNode;
14
+ }
15
+ export interface WizardProps {
16
+ className?: string;
17
+ continueLabel: string;
18
+ /** Label on the last step. */
19
+ finishLabel: string;
20
+ labels?: {
21
+ back: string;
22
+ close: string;
23
+ step: (index: number, total: number) => string;
24
+ };
25
+ onClose?: () => void;
26
+ /** Fired from the last step's CTA. */
27
+ onDone: () => void;
28
+ /** Every step change, including backwards — for analytics and autosave. */
29
+ onStep?: (index: number) => void;
30
+ steps: WizardStep[];
31
+ }
32
+ /**
33
+ * A short, one-question-per-screen flow: mood → cause → note, or any other
34
+ * sequence a viewer walks once and abandons easily.
35
+ *
36
+ * The step index is the wizard's; the answers are not. A wizard that owned the
37
+ * answers would have to know their shape, and every product's are different —
38
+ * so each step is given its content and reports back through `canContinue`,
39
+ * which is the only thing the shell needs to know.
40
+ *
41
+ * Progress is dots rather than a bar: a bar implies a percentage of work done,
42
+ * and three questions are three questions. The close control is always present
43
+ * — a flow the viewer cannot leave is a trap, and leaving is the most common
44
+ * thing anyone does with one of these.
45
+ */
46
+ export declare function Wizard({ className, continueLabel, finishLabel, labels, onClose, onDone, onStep, steps, }: WizardProps): import("react").JSX.Element;
47
+ export interface ChoiceGridOption {
48
+ disabled?: boolean;
49
+ icon?: ReactNode;
50
+ id: string;
51
+ label: ReactNode;
52
+ }
53
+ export interface ChoiceGridProps {
54
+ className?: string;
55
+ /** Cap a multi-select. Options past the cap disable rather than disappear,
56
+ so the grid does not reflow under the viewer's finger. */
57
+ max?: number;
58
+ multiple?: boolean;
59
+ onChange: (selected: string[]) => void;
60
+ options: ChoiceGridOption[];
61
+ selected: string[];
62
+ }
63
+ /**
64
+ * The grid of icon tiles a wizard step is usually made of.
65
+ *
66
+ * Single-select renders radios and multi-select renders checkboxes — stated in
67
+ * ARIA rather than implied by how many are lit, because "pick one" and "pick
68
+ * any" are different promises and only one of them is visible in a grid.
69
+ */
70
+ export declare function ChoiceGrid({ className, max, multiple, onChange, options, selected, }: ChoiceGridProps): import("react").JSX.Element;
@@ -0,0 +1,104 @@
1
+ export { ActivityFeed, AdminShell, DetailHeader, FilterChips } from './components/admin-shell';
2
+ export type { ActivityEvent, ActivityFeedProps, AdminNavGroup, AdminNavItem, AdminShellProps, DetailHeaderProps, FilterChip, FilterChipsProps, } from './components/admin-shell';
3
+ export { AppShell } from './components/app-shell';
4
+ export type { AppShellProps } from './components/app-shell';
5
+ export { AuthScreen } from './components/auth-screen';
6
+ export type { AuthScreenProps } from './components/auth-screen';
7
+ export { Avatar } from './components/avatar';
8
+ export type { AvatarProps, AvatarSize } from './components/avatar';
9
+ export { AvatarRing, ProfileHeader } from './components/profile-header';
10
+ export type { AvatarRingProps, ProfileHeaderProps } from './components/profile-header';
11
+ export { Badge } from './components/badge';
12
+ export type { BadgeProps, BadgeSize, BadgeTone, BadgeVariant } from './components/badge';
13
+ export { Banner } from './components/banner';
14
+ export type { BannerProps, BannerTone } from './components/banner';
15
+ export { Breadcrumb } from './components/breadcrumb';
16
+ export type { BreadcrumbProps, Crumb } from './components/breadcrumb';
17
+ export { Button } from './components/button';
18
+ export type { ButtonProps, ButtonSize, ButtonVariant } from './components/button';
19
+ export { Card } from './components/card';
20
+ export type { CardPadding, CardProps, CardVariant } from './components/card';
21
+ export { ActionBar, OptionCard, OrderSummary } from './components/checkout';
22
+ export type { ActionBarProps, OptionCardProps, OrderSummaryProps, SummaryLine, } from './components/checkout';
23
+ export { Chat } from './components/chat';
24
+ export type { ChatAttachment, ChatMediaKind, ChatMessage, ChatProps } from './components/chat';
25
+ export { ChatComposer } from './components/chat-composer';
26
+ export type { ChatComposerProps, ChatDraft } from './components/chat-composer';
27
+ export { Checkbox, Switch } from './components/choice';
28
+ export type { CheckboxProps, SwitchProps } from './components/choice';
29
+ export { Combobox } from './components/combobox';
30
+ export type { ComboboxOption, ComboboxProps } from './components/combobox';
31
+ export { Calendar, DateField, DatePicker } from './components/date-field';
32
+ export type { CalendarProps, CalendarSystem, DateFieldProps, DatePickerProps, IsoDate, } from './components/date-field';
33
+ export { addDays, addMonths, formatNumeric, monthLength, parseNumeric, partsOf, fromParts, startOfMonth, todayIso, } from './lib/calendars';
34
+ export type { CalendarParts } from './lib/calendars';
35
+ export { Dialog } from './components/dialog';
36
+ export type { DialogProps } from './components/dialog';
37
+ export { EmptyState } from './components/empty-state';
38
+ export type { EmptyStateProps } from './components/empty-state';
39
+ export { Progress, Skeleton, Spinner } from './components/feedback';
40
+ export type { ProgressProps, SkeletonProps, SpinnerProps } from './components/feedback';
41
+ export { ResourceMeter } from './components/resource-meter';
42
+ export type { ResourceMeterProps, ResourceMeterTone } from './components/resource-meter';
43
+ export { Input, Select, Textarea } from './components/field';
44
+ export type { InputProps, SelectOption, SelectProps, TextareaProps } from './components/field';
45
+ export { Icon, iconNames } from './components/icon';
46
+ export type { IconName, IconProps, IconSize, IconTone } from './components/icon';
47
+ export { IconButton } from './components/icon-button';
48
+ export type { IconButtonProps, IconButtonSize, IconButtonVariant } from './components/icon-button';
49
+ export { AppFrame, Inline, Stack } from './components/layout';
50
+ export { List, ListRow } from './components/list';
51
+ export type { ListProps, ListRowProps } from './components/list';
52
+ export { Menu, Popover } from './components/menu';
53
+ export type { MenuAction, MenuHeading, MenuItem, MenuProps, MenuSeparator, PopoverProps } from './components/menu';
54
+ export { Onboarding } from './components/onboarding';
55
+ export type { OnboardingProps, OnboardingSlide } from './components/onboarding';
56
+ export { OtpInput } from './components/otp-input';
57
+ export type { OtpInputProps } from './components/otp-input';
58
+ export { Pagination } from './components/pagination';
59
+ export type { PaginationProps } from './components/pagination';
60
+ export { PasswordField, scorePassword } from './components/password-field';
61
+ export type { PasswordFieldProps, PasswordStrength } from './components/password-field';
62
+ export { PhoneField, toE164 } from './components/phone-field';
63
+ export type { PhoneFieldProps } from './components/phone-field';
64
+ export { PlanCard } from './components/plan-card';
65
+ export type { PlanCardProps, PlanFeature } from './components/plan-card';
66
+ export { PlanPicker } from './components/plan-picker';
67
+ export type { BillingCycle, PlanOffer, PlanPickerProps } from './components/plan-picker';
68
+ export { ProfileScreen } from './components/profile-screen';
69
+ export type { ProfileRow, ProfileScreenProps, ProfileSection } from './components/profile-screen';
70
+ export { SectionHeader } from './components/section-header';
71
+ export type { SectionHeaderProps } from './components/section-header';
72
+ export { Segmented } from './components/segmented';
73
+ export type { SegmentedOption, SegmentedProps } from './components/segmented';
74
+ export { SignInFlow } from './components/sign-in-flow';
75
+ export type { SignInCopy, SignInFlowProps, SignInMethod } from './components/sign-in-flow';
76
+ export { Sheet } from './components/sheet';
77
+ export type { SheetProps } from './components/sheet';
78
+ export { Slider } from './components/slider';
79
+ export type { SliderProps } from './components/slider';
80
+ export { Stat } from './components/stat';
81
+ export type { StatProps } from './components/stat';
82
+ export { Stepper } from './components/stepper';
83
+ export type { StepperProps } from './components/stepper';
84
+ export { TaskProgress } from './components/task-progress';
85
+ export type { TaskProgressProps, TaskStep, TaskStepStatus } from './components/task-progress';
86
+ export { Table } from './components/table';
87
+ export type { SortDirection, TableColumn, TableProps } from './components/table';
88
+ export { TabBar } from './components/tab-bar';
89
+ export type { TabBarItem, TabBarProps } from './components/tab-bar';
90
+ export { Tabs } from './components/tabs';
91
+ export type { TabOption, TabsProps } from './components/tabs';
92
+ export { NimProvider, useNim, useSchemeToggle } from './components/theme';
93
+ export type { NimColorway, NimDirection, NimProviderProps, NimScheme, NimStyle, } from './components/theme';
94
+ export { ToastProvider, useToast } from './components/toast';
95
+ export type { ToastOptions, ToastTone } from './components/toast';
96
+ export { Tooltip } from './components/tooltip';
97
+ export type { TooltipProps } from './components/tooltip';
98
+ export { ChoiceGrid, Wizard } from './components/wizard';
99
+ export type { ChoiceGridOption, ChoiceGridProps, WizardProps, WizardStep, } from './components/wizard';
100
+ export { Body, Caption, Display, Label, Rule, Title } from './components/typography';
101
+ export { COUNTRIES, countryByDial, countryByIso2, countryNamer, toAsciiDigits, } from './lib/countries';
102
+ export type { Country } from './lib/countries';
103
+ export { cn } from './lib/cn';
104
+ export type { ClassValue } from './lib/cn';
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Calendar arithmetic for the two systems the kit draws: Gregorian and
3
+ * Jalali (Solar Hijri).
4
+ *
5
+ * There is no conversion table and no leap-year rule in this file, because the
6
+ * platform already ships one: `Intl.DateTimeFormat` with `-u-ca-persian` is
7
+ * ICU's Persian calendar, and it is the same implementation a browser uses to
8
+ * label a date anywhere else. So the direction that is hard — Gregorian to
9
+ * Jalali — is asked of `Intl`, and the direction that is easy — Jalali back to
10
+ * Gregorian — is a close estimate corrected against that same answer until it
11
+ * round-trips. Every value this module returns has therefore been checked
12
+ * against the platform's own calendar rather than against a table that has to
13
+ * be maintained here and goes wrong in 1403 or 2049.
14
+ *
15
+ * The kit's value type never changes: an `IsoDate` is always the Gregorian
16
+ * `YYYY-MM-DD`, in every calendar system. What the viewer reads and what the
17
+ * API receives are different questions, and only the first one has a calendar.
18
+ */
19
+ /** ISO `YYYY-MM-DD`, Gregorian, always. The kit never invents a date type. */
20
+ export type IsoDate = string;
21
+ /** The calendar a grid is drawn in — never what a value is stored in. */
22
+ export type CalendarSystem = 'gregory' | 'persian';
23
+ export interface CalendarParts {
24
+ day: number;
25
+ month: number;
26
+ year: number;
27
+ }
28
+ export declare const isoOf: (date: Date) => IsoDate;
29
+ export declare const dateOf: (value: IsoDate) => Date;
30
+ export declare const todayIso: () => IsoDate;
31
+ /** The calendar fields a viewer of `system` would read off this instant. */
32
+ export declare function partsOf(value: IsoDate, system: CalendarSystem): CalendarParts;
33
+ /**
34
+ * The Gregorian date on which `parts` falls in `system`.
35
+ *
36
+ * For Jalali this starts from the mean-year estimate and walks to the answer,
37
+ * comparing against `partsOf` — which is ICU. The estimate is never more than
38
+ * a few days out, and the loop is bounded, so a bad input fails by returning
39
+ * its best effort rather than by spinning.
40
+ */
41
+ export declare function fromParts(parts: CalendarParts, system: CalendarSystem): IsoDate;
42
+ /** The first day of the month `value` falls in, in `system`. */
43
+ export declare function startOfMonth(value: IsoDate, system: CalendarSystem): IsoDate;
44
+ /** `delta` months on from `value`, clamped into the target month's length. */
45
+ export declare function addMonths(value: IsoDate, delta: number, system: CalendarSystem): IsoDate;
46
+ /**
47
+ * How many days that month holds — measured, not tabulated. The distance to
48
+ * the first of the next month is the length, whatever the leap rule says, so
49
+ * an Esfand of 30 days needs no special case here.
50
+ */
51
+ export declare function monthLength(year: number, month: number, system: CalendarSystem): number;
52
+ export declare const addDays: (value: IsoDate, days: number) => IsoDate;
53
+ /** 0 = Sunday. The week's shape is the same fact in every calendar. */
54
+ export declare const weekdayOf: (value: IsoDate) => number;
55
+ /**
56
+ * The locale tag that puts `Intl` into `system`. A `-u-ca-` extension already
57
+ * on the tag wins, so an app asking for `fa-IR-u-ca-gregory` keeps it.
58
+ */
59
+ export declare function localeFor(locale: string | undefined, system: CalendarSystem): string;
60
+ /**
61
+ * The calendar an `fa` reader expects. Persian interfaces run on the Jalali
62
+ * calendar; everything else this kit ships in runs on the Gregorian one.
63
+ */
64
+ export declare const defaultSystem: (locale: string | undefined) => CalendarSystem;
65
+ /** Persian weeks begin on Saturday; the Gregorian ones here on Monday. */
66
+ export declare const defaultWeekStart: (system: CalendarSystem) => number;
67
+ /**
68
+ * `۱۴۰۴/۰۶/۰۱` — year first, zero-padded, in the locale's digits.
69
+ *
70
+ * Deliberately not `Intl`'s numeric pattern, which would give `۰۱/۰۶/۱۴۰۴ ه.ش`
71
+ * under an English locale on the Jalali calendar: field order and an era
72
+ * suffix that no Iranian writes and this module's parser cannot read back. A
73
+ * Jalali date is written biggest-unit-first everywhere it is written at all,
74
+ * so `formatNumeric` and `parseNumeric` agree by construction.
75
+ */
76
+ export declare function formatNumeric(value: IsoDate, locale: string | undefined, system: CalendarSystem): string;
77
+ /**
78
+ * Reads `1404/06/01`, `۱۴۰۴-۰۶-۰۱`, or anything else with three numbers in
79
+ * year, month, day order. Returns null rather than guessing at two.
80
+ */
81
+ export declare function parseNumeric(input: string, system: CalendarSystem): IsoDate | null;
@@ -0,0 +1,7 @@
1
+ /**
2
+ * The kit's only class-name helper. nim components compose a small, fixed set
3
+ * of semantic class names, so a full `clsx`-style dependency would buy nothing
4
+ * that this does not already do.
5
+ */
6
+ export type ClassValue = string | false | null | undefined;
7
+ export declare const cn: (...values: ClassValue[]) => string;