@azmr/ui 0.1.0 → 0.2.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 (91) hide show
  1. package/README.md +171 -0
  2. package/dist/avatar.d.ts +58 -0
  3. package/dist/avatar.js +84 -0
  4. package/dist/breadcrumb.d.ts +47 -0
  5. package/dist/breadcrumb.js +120 -0
  6. package/dist/button-CYt2Zw3D.d.ts +64 -0
  7. package/dist/button.d.ts +54 -0
  8. package/dist/button.js +19 -0
  9. package/dist/chunk-2RIWL363.js +27 -0
  10. package/dist/chunk-2TQSHVXA.js +12 -0
  11. package/dist/chunk-7EOSDFS3.js +10 -0
  12. package/dist/chunk-C2HKIPLQ.js +118 -0
  13. package/dist/chunk-CAJLW6K2.js +16 -0
  14. package/dist/chunk-CZJZYN54.js +36 -0
  15. package/dist/chunk-EE4V6XMB.js +35 -0
  16. package/dist/chunk-EFHRRLAW.js +211 -0
  17. package/dist/chunk-GLB75NT3.js +21 -0
  18. package/dist/chunk-GX2YEJ43.js +36 -0
  19. package/dist/chunk-LTOLV67A.js +19 -0
  20. package/dist/chunk-LZMX27IZ.js +10 -0
  21. package/dist/chunk-NIIDYIZA.js +1 -0
  22. package/dist/chunk-Q4PPM2SU.js +97 -0
  23. package/dist/chunk-WVE2E37B.js +20 -0
  24. package/dist/chunk-XRZHP6BD.js +92 -0
  25. package/dist/disclosure.d.ts +72 -0
  26. package/dist/disclosure.js +221 -0
  27. package/dist/display.d.ts +111 -0
  28. package/dist/display.js +237 -0
  29. package/dist/floating.d.ts +81 -0
  30. package/dist/floating.js +231 -0
  31. package/dist/hooks.d.ts +33 -0
  32. package/dist/hooks.js +55 -0
  33. package/dist/icons/lucide.d.ts +77 -0
  34. package/dist/icons/lucide.js +135 -0
  35. package/dist/icons/mui-map.d.ts +1268 -0
  36. package/dist/icons/mui-map.js +352 -0
  37. package/dist/icons.d.ts +48 -0
  38. package/dist/icons.js +19 -0
  39. package/dist/index.d.ts +238 -3
  40. package/dist/index.js +242 -15
  41. package/dist/input.d.ts +14 -0
  42. package/dist/input.js +8 -0
  43. package/dist/layout/mui-map.d.ts +80 -0
  44. package/dist/layout/mui-map.js +104 -0
  45. package/dist/layout.d.ts +89 -0
  46. package/dist/layout.js +455 -0
  47. package/dist/lib.d.ts +11 -0
  48. package/dist/lib.js +6 -0
  49. package/dist/menu.d.ts +105 -0
  50. package/dist/menu.js +56 -0
  51. package/dist/modal.d.ts +105 -0
  52. package/dist/modal.js +273 -0
  53. package/dist/motion.css +295 -0
  54. package/dist/pagination.d.ts +82 -0
  55. package/dist/pagination.js +211 -0
  56. package/dist/presets.d.ts +97 -0
  57. package/dist/presets.js +94 -0
  58. package/dist/progress.d.ts +70 -0
  59. package/dist/progress.js +138 -0
  60. package/dist/react.d.ts +81 -0
  61. package/dist/react.js +281 -0
  62. package/dist/responsive-YJBnvsjt.d.ts +69 -0
  63. package/dist/scroll-area.d.ts +30 -0
  64. package/dist/scroll-area.js +80 -0
  65. package/dist/shared-Fkx-sjPt.d.ts +15 -0
  66. package/dist/spinner.d.ts +18 -0
  67. package/dist/spinner.js +39 -0
  68. package/dist/split-button.d.ts +32 -0
  69. package/dist/split-button.js +54 -0
  70. package/dist/stepper.d.ts +27 -0
  71. package/dist/stepper.js +104 -0
  72. package/dist/styles.css +24 -0
  73. package/dist/table.d.ts +52 -0
  74. package/dist/table.js +124 -0
  75. package/dist/theme.d.ts +111 -0
  76. package/dist/theme.js +414 -0
  77. package/dist/toast.d.ts +77 -0
  78. package/dist/toast.js +203 -0
  79. package/dist/toggle.d.ts +55 -0
  80. package/dist/toggle.js +88 -0
  81. package/dist/tokens.css +337 -0
  82. package/dist/transition.d.ts +51 -0
  83. package/dist/transition.js +79 -0
  84. package/dist/types-BBudf463.d.ts +39 -0
  85. package/dist/typography/mui-map.d.ts +91 -0
  86. package/dist/typography/mui-map.js +62 -0
  87. package/dist/typography.d.ts +90 -0
  88. package/dist/typography.js +193 -0
  89. package/dist/useSignal-C-3ZGURN.d.ts +21 -0
  90. package/dist/variants-De0c0ucO.d.ts +60 -0
  91. package/package.json +167 -12
package/dist/index.d.ts CHANGED
@@ -1,5 +1,172 @@
1
+ export { a as Button, b as ButtonProps, c as buttonVariants } from './button-CYt2Zw3D.js';
2
+ export { Input, InputProps } from './input.js';
1
3
  import * as react from 'react';
4
+ import { SVGProps, HTMLAttributes, ReactNode, ElementType, ComponentPropsWithoutRef, Ref, ReactElement, ComponentType } from 'react';
2
5
  import { Signal } from '@azmr/core';
6
+ import { ClassValue } from 'clsx';
7
+ export { ClassValue } from 'clsx';
8
+ export { u as useSignal } from './useSignal-C-3ZGURN.js';
9
+ import 'class-variance-authority';
10
+ import '@base-ui/react/button';
11
+ import 'class-variance-authority/types';
12
+ import '@base-ui/react/input';
13
+
14
+ interface SpinnerProps extends Omit<SVGProps<SVGSVGElement>, "ref"> {
15
+ /**
16
+ * Accessible name. When set the spinner is announced as a status ("Loading customers");
17
+ * when omitted it is decorative and hidden from assistive technology (use that when the
18
+ * surrounding control already says it is busy, as `Button loading` does).
19
+ */
20
+ label?: string;
21
+ }
22
+ /**
23
+ * An indeterminate progress indicator. It keeps spinning under `prefers-reduced-motion`
24
+ * (`data-motion="essential"`) because a frozen spinner reads as a hung page.
25
+ */
26
+ declare const Spinner: react.ForwardRefExoticComponent<SpinnerProps & react.RefAttributes<SVGSVGElement>>;
27
+
28
+ /**
29
+ * The type scale: every variant's semantic element and its classes, in one place. Colours are
30
+ * tokens only. Classes are spelled out in full so the Tailwind scanner finds them in `dist`.
31
+ */
32
+ declare const typographyVariants: {
33
+ readonly h1: {
34
+ readonly element: "h1";
35
+ readonly classes: "scroll-m-20 text-4xl font-bold tracking-tight text-foreground";
36
+ };
37
+ readonly h2: {
38
+ readonly element: "h2";
39
+ readonly classes: "scroll-m-20 text-3xl font-semibold tracking-tight text-foreground";
40
+ };
41
+ readonly h3: {
42
+ readonly element: "h3";
43
+ readonly classes: "scroll-m-20 text-2xl font-semibold tracking-tight text-foreground";
44
+ };
45
+ readonly h4: {
46
+ readonly element: "h4";
47
+ readonly classes: "scroll-m-20 text-xl font-semibold tracking-tight text-foreground";
48
+ };
49
+ readonly h5: {
50
+ readonly element: "h5";
51
+ readonly classes: "scroll-m-20 text-lg font-semibold text-foreground";
52
+ };
53
+ readonly h6: {
54
+ readonly element: "h6";
55
+ readonly classes: "scroll-m-20 text-base font-semibold text-foreground";
56
+ };
57
+ readonly lead: {
58
+ readonly element: "p";
59
+ readonly classes: "text-lg text-muted-foreground";
60
+ };
61
+ readonly body: {
62
+ readonly element: "p";
63
+ readonly classes: "text-base";
64
+ };
65
+ readonly small: {
66
+ readonly element: "p";
67
+ readonly classes: "text-sm";
68
+ };
69
+ readonly caption: {
70
+ readonly element: "span";
71
+ readonly classes: "text-xs text-muted-foreground";
72
+ };
73
+ readonly overline: {
74
+ readonly element: "span";
75
+ readonly classes: "text-xs font-medium uppercase tracking-wider text-muted-foreground";
76
+ };
77
+ };
78
+ type TypographyVariant = keyof typeof typographyVariants;
79
+ declare const ALIGN_CLASSES: {
80
+ readonly left: "text-left";
81
+ readonly center: "text-center";
82
+ readonly right: "text-right";
83
+ readonly justify: "text-justify";
84
+ };
85
+ type TypographyAlign = keyof typeof ALIGN_CLASSES;
86
+
87
+ interface TypographyOwnProps {
88
+ /** The type-scale step. It picks the semantic element and the look. Default `body`. */
89
+ variant?: TypographyVariant;
90
+ align?: TypographyAlign;
91
+ /** Truncate to one line with an ellipsis. */
92
+ noWrap?: boolean;
93
+ /** Add a small bottom margin (MUI's `gutterBottom`). */
94
+ gutterBottom?: boolean;
95
+ }
96
+ type TypographyProps<T extends ElementType = "p"> = TypographyOwnProps & {
97
+ /** Render a different element or component, keeping the look: `variant="h1" as="h2"`. */
98
+ as?: T;
99
+ } & Omit<ComponentPropsWithoutRef<T>, keyof TypographyOwnProps | "as">;
100
+ /**
101
+ * Text with a type-scale variant. The variant decides the semantic element (`h1` to `h6`, `p`,
102
+ * `span`), and `as` overrides it without changing the look. Server-safe.
103
+ */
104
+ declare const Typography: <T extends ElementType = "p">(props: TypographyProps<T> & {
105
+ ref?: Ref<HTMLElement>;
106
+ }) => ReactElement | null;
107
+ type HeadingLevel = 1 | 2 | 3 | 4 | 5 | 6;
108
+ type HeadingSize = "h1" | "h2" | "h3" | "h4" | "h5" | "h6";
109
+ interface HeadingProps extends Omit<HTMLAttributes<HTMLHeadingElement>, "children">, Omit<TypographyOwnProps, "variant"> {
110
+ /** The semantic level (`<h2>`). Default 2. */
111
+ level?: HeadingLevel;
112
+ /** The visual size when it should differ from the level, e.g. a quiet `<h2>`. */
113
+ size?: HeadingSize;
114
+ children?: ReactNode;
115
+ }
116
+ /** A heading whose semantic level and visual size are separate decisions. */
117
+ declare const Heading: react.ForwardRefExoticComponent<HeadingProps & react.RefAttributes<HTMLHeadingElement>>;
118
+ declare const TONE_CLASSES: {
119
+ readonly muted: "text-muted-foreground";
120
+ readonly destructive: "text-destructive";
121
+ readonly success: "text-success";
122
+ readonly warning: "text-warning-text";
123
+ readonly info: "text-info";
124
+ };
125
+ declare const SIZE_CLASSES: {
126
+ readonly sm: "text-sm";
127
+ readonly base: "text-base";
128
+ readonly lg: "text-lg";
129
+ };
130
+ declare const WEIGHT_CLASSES: {
131
+ readonly normal: "font-normal";
132
+ readonly medium: "font-medium";
133
+ readonly semibold: "font-semibold";
134
+ readonly bold: "font-bold";
135
+ };
136
+ interface TextProps extends HTMLAttributes<HTMLElement> {
137
+ as?: "p" | "span" | "div" | "label" | "strong" | "em" | "small";
138
+ size?: keyof typeof SIZE_CLASSES;
139
+ tone?: keyof typeof TONE_CLASSES;
140
+ weight?: keyof typeof WEIGHT_CLASSES;
141
+ }
142
+ /** Running text. A paragraph by default; `tone` uses semantic colour tokens. */
143
+ declare const Text: react.ForwardRefExoticComponent<TextProps & react.RefAttributes<HTMLElement>>;
144
+ declare const UNDERLINE_CLASSES: {
145
+ readonly always: "underline";
146
+ readonly hover: "hover:underline focus-visible:underline";
147
+ readonly none: "no-underline";
148
+ };
149
+ interface LinkOwnProps {
150
+ /**
151
+ * `always` (default) keeps links distinguishable without relying on colour alone;
152
+ * `hover` underlines on hover and focus; `none` removes it.
153
+ */
154
+ underline?: keyof typeof UNDERLINE_CLASSES;
155
+ /** Opens in a new tab with `rel="noopener noreferrer"` and tells screen readers. */
156
+ external?: boolean;
157
+ }
158
+ type LinkProps<T extends ElementType = "a"> = LinkOwnProps & {
159
+ /** Render a router link: `<Link as={NextLink} href="/x">`. */
160
+ as?: T;
161
+ } & Omit<ComponentPropsWithoutRef<T>, keyof LinkOwnProps | "as">;
162
+ /** A link. Underlined by default, with a full-strength focus ring. Server-safe. */
163
+ declare const Link: <T extends ElementType = "a">(props: LinkProps<T> & {
164
+ ref?: Ref<HTMLAnchorElement>;
165
+ }) => ReactElement | null;
166
+ /** Inline code. */
167
+ declare const Code: react.ForwardRefExoticComponent<HTMLAttributes<HTMLElement> & react.RefAttributes<HTMLElement>>;
168
+ /** A keyboard key, for documenting shortcuts. */
169
+ declare const Kbd: react.ForwardRefExoticComponent<HTMLAttributes<HTMLElement> & react.RefAttributes<HTMLElement>>;
3
170
 
4
171
  interface GridProps<T extends Record<string, unknown>> {
5
172
  signal: Signal<T[]>;
@@ -15,9 +182,77 @@ interface GridProps<T extends Record<string, unknown>> {
15
182
  */
16
183
  declare function Grid<T extends Record<string, unknown>>({ signal, columns, labels, emptyMessage, }: GridProps<T>): react.JSX.Element;
17
184
 
185
+ /** The size scale. A number is a literal pixel size (width and height). */
186
+ type IconSize = "xs" | "sm" | "md" | "lg" | "xl" | number;
187
+ /**
188
+ * The props the Icon passes to the icon component it renders. Lucide, Tabler and plain
189
+ * `(props: SVGProps<SVGSVGElement>) => <svg />` components all accept these, so any of them
190
+ * can be used as an icon. Every prop is optional so the library components assign to it.
191
+ */
192
+ interface IconRenderProps {
193
+ className?: string;
194
+ width?: number | string;
195
+ height?: number | string;
196
+ strokeWidth?: number | string;
197
+ role?: string;
198
+ "aria-hidden"?: boolean | "true" | "false";
199
+ "aria-label"?: string;
200
+ "aria-labelledby"?: string;
201
+ "data-motion"?: string;
202
+ }
203
+ type IconComponent = ComponentType<IconRenderProps>;
204
+ interface IconProps extends Omit<SVGProps<SVGSVGElement>, "ref" | "size" | "children"> {
205
+ /** The icon to render: a Lucide or Tabler icon, or your own SVG component. */
206
+ icon?: IconComponent;
207
+ /** Looks the icon up in the registry (`registerIcons`). `icon` wins when both are given. */
208
+ name?: string;
209
+ /** `xs` .. `xl` follow the size tokens; a number is a pixel size. Default `md`. */
210
+ size?: IconSize;
211
+ /** Turns the icon into a loading indicator. It keeps spinning under reduced motion. */
212
+ spin?: boolean;
213
+ /**
214
+ * Decorative by default (`aria-hidden`). Give `aria-label` or `aria-labelledby` to make the
215
+ * icon meaningful: it then has `role="img"` and an accessible name.
216
+ */
217
+ "aria-label"?: string;
218
+ "aria-labelledby"?: string;
219
+ }
220
+
221
+ /**
222
+ * Builds an `<Icon name="...">` bound to a fixed set of icons, with the names type-checked.
223
+ * Unlike `registerIcons`, nothing is global and only the icons you list are bundled.
224
+ *
225
+ * ```tsx
226
+ * const { Icon } = createIconSet({ check: Check, "my-logo": MyLogo });
227
+ * <Icon name="check" />
228
+ * ```
229
+ */
230
+ declare function createIconSet<const T extends Record<string, IconComponent>>(icons: T): {
231
+ Icon: react.ForwardRefExoticComponent<Omit<IconProps, "name" | "icon"> & {
232
+ name: keyof T & string;
233
+ } & react.RefAttributes<SVGSVGElement>>;
234
+ names: readonly (keyof T & string)[];
235
+ };
236
+
237
+ /**
238
+ * Renders an icon component (Lucide, Tabler or your own SVG) with consistent size, stroke,
239
+ * motion and accessibility. Server-safe: no hooks, no `"use client"`.
240
+ *
241
+ * Decorative by default; `aria-label` / `aria-labelledby` make it a labelled image.
242
+ */
243
+ declare const Icon: react.ForwardRefExoticComponent<IconProps & react.RefAttributes<SVGSVGElement>>;
244
+
245
+ /**
246
+ * Registers custom icons for `<Icon name="..." />`. A later registration replaces an earlier one
247
+ * with the same name. Validated up front and atomic: if any entry is invalid, none is registered.
248
+ */
249
+ declare function registerIcons(icons: Record<string, IconComponent>): void;
250
+
18
251
  /**
19
- * React hook that subscribes to a Signal and triggers re-renders on change.
252
+ * Merge class names, resolving conflicting Tailwind utilities so the last one
253
+ * wins (`cn("p-2", "p-4")` → `"p-4"`). Every component accepts `className` and
254
+ * passes it through `cn` last, so callers can always override a default.
20
255
  */
21
- declare function useSignal<T>(signal: Signal<T>): T;
256
+ declare function cn(...inputs: ClassValue[]): string;
22
257
 
23
- export { Grid, useSignal };
258
+ export { Code, Grid, Heading, type HeadingProps, Icon, type IconComponent, type IconProps, type IconSize, Kbd, Link, type LinkProps, Spinner, type SpinnerProps, Text, type TextProps, Typography, type TypographyProps, type TypographyVariant, cn, createIconSet, registerIcons };
package/dist/index.js CHANGED
@@ -1,16 +1,211 @@
1
- // src/useSignal.ts
2
- import { useEffect, useState } from "react";
3
- function useSignal(signal) {
4
- const [value, setValue] = useState(() => signal.get());
5
- useEffect(() => {
6
- setValue(signal.get());
7
- return signal.subscribe(setValue);
8
- }, [signal]);
9
- return value;
1
+ "use client";
2
+ import {
3
+ Icon,
4
+ assertIconEntry,
5
+ registerIcons,
6
+ warnMissingIcon
7
+ } from "./chunk-XRZHP6BD.js";
8
+ import {
9
+ useSignal
10
+ } from "./chunk-CAJLW6K2.js";
11
+ import "./chunk-NIIDYIZA.js";
12
+ import "./chunk-CZJZYN54.js";
13
+ import {
14
+ Button,
15
+ Spinner,
16
+ buttonVariants
17
+ } from "./chunk-C2HKIPLQ.js";
18
+ import "./chunk-EE4V6XMB.js";
19
+ import {
20
+ Input
21
+ } from "./chunk-GX2YEJ43.js";
22
+ import {
23
+ cn
24
+ } from "./chunk-2TQSHVXA.js";
25
+
26
+ // src/components/typography/typography.tsx
27
+ import {
28
+ forwardRef
29
+ } from "react";
30
+
31
+ // src/components/typography/variants.ts
32
+ var typographyVariants = {
33
+ h1: { element: "h1", classes: "scroll-m-20 text-4xl font-bold tracking-tight text-foreground" },
34
+ h2: {
35
+ element: "h2",
36
+ classes: "scroll-m-20 text-3xl font-semibold tracking-tight text-foreground"
37
+ },
38
+ h3: {
39
+ element: "h3",
40
+ classes: "scroll-m-20 text-2xl font-semibold tracking-tight text-foreground"
41
+ },
42
+ h4: {
43
+ element: "h4",
44
+ classes: "scroll-m-20 text-xl font-semibold tracking-tight text-foreground"
45
+ },
46
+ h5: { element: "h5", classes: "scroll-m-20 text-lg font-semibold text-foreground" },
47
+ h6: { element: "h6", classes: "scroll-m-20 text-base font-semibold text-foreground" },
48
+ lead: { element: "p", classes: "text-lg text-muted-foreground" },
49
+ body: { element: "p", classes: "text-base" },
50
+ small: { element: "p", classes: "text-sm" },
51
+ caption: { element: "span", classes: "text-xs text-muted-foreground" },
52
+ overline: {
53
+ element: "span",
54
+ classes: "text-xs font-medium uppercase tracking-wider text-muted-foreground"
55
+ }
56
+ };
57
+ var ALIGN_CLASSES = {
58
+ left: "text-left",
59
+ center: "text-center",
60
+ right: "text-right",
61
+ justify: "text-justify"
62
+ };
63
+
64
+ // src/components/typography/typography.tsx
65
+ import { jsx, jsxs } from "react/jsx-runtime";
66
+ function TypographyImpl({
67
+ variant = "body",
68
+ as,
69
+ align,
70
+ noWrap,
71
+ gutterBottom,
72
+ className,
73
+ ...props
74
+ }, ref) {
75
+ const definition = typographyVariants[variant];
76
+ const Component = as ?? definition.element;
77
+ return /* @__PURE__ */ jsx(
78
+ Component,
79
+ {
80
+ ref,
81
+ className: cn(
82
+ definition.classes,
83
+ align && ALIGN_CLASSES[align],
84
+ // `truncate` needs a block-level box: on an inline span (caption, overline, or any
85
+ // `as="span"`) the ellipsis would never show and the text would overflow.
86
+ noWrap && cn("truncate", Component === "span" && "block"),
87
+ gutterBottom && "mb-[0.35em]",
88
+ className
89
+ ),
90
+ ...props
91
+ }
92
+ );
10
93
  }
94
+ var Typography = forwardRef(TypographyImpl);
95
+ var Heading = forwardRef(function Heading2({ level = 2, size, ...props }, ref) {
96
+ return /* @__PURE__ */ jsx(
97
+ Typography,
98
+ {
99
+ ref,
100
+ as: `h${level}`,
101
+ variant: size ?? `h${level}`,
102
+ ...props
103
+ }
104
+ );
105
+ });
106
+ var TONE_CLASSES = {
107
+ muted: "text-muted-foreground",
108
+ destructive: "text-destructive",
109
+ success: "text-success",
110
+ warning: "text-warning-text",
111
+ info: "text-info"
112
+ };
113
+ var SIZE_CLASSES = { sm: "text-sm", base: "text-base", lg: "text-lg" };
114
+ var WEIGHT_CLASSES = {
115
+ normal: "font-normal",
116
+ medium: "font-medium",
117
+ semibold: "font-semibold",
118
+ bold: "font-bold"
119
+ };
120
+ var Text = forwardRef(function Text2({ as: Component = "p", size = "base", tone, weight, className, ...props }, ref) {
121
+ return /* @__PURE__ */ jsx(
122
+ Component,
123
+ {
124
+ ref,
125
+ className: cn(
126
+ SIZE_CLASSES[size],
127
+ tone && TONE_CLASSES[tone],
128
+ weight && WEIGHT_CLASSES[weight],
129
+ className
130
+ ),
131
+ ...props
132
+ }
133
+ );
134
+ });
135
+ var UNDERLINE_CLASSES = {
136
+ always: "underline",
137
+ hover: "hover:underline focus-visible:underline",
138
+ none: "no-underline"
139
+ };
140
+ function LinkImpl({
141
+ as: Component = "a",
142
+ underline = "always",
143
+ external,
144
+ target: targetProp,
145
+ rel: relProp,
146
+ className,
147
+ children,
148
+ ...props
149
+ }, ref) {
150
+ const target = targetProp ?? (external ? "_blank" : void 0);
151
+ const opensNewTab = target === "_blank";
152
+ const rel = opensNewTab ? safeRel(relProp) : relProp;
153
+ return /* @__PURE__ */ jsxs(
154
+ Component,
155
+ {
156
+ ref,
157
+ className: cn(
158
+ "rounded-sm font-medium text-primary underline-offset-4 outline-none",
159
+ "focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
160
+ UNDERLINE_CLASSES[underline],
161
+ className
162
+ ),
163
+ target,
164
+ rel,
165
+ ...props,
166
+ children: [
167
+ children,
168
+ opensNewTab && /* @__PURE__ */ jsx("span", { className: "sr-only", children: "(opens in a new tab)" })
169
+ ]
170
+ }
171
+ );
172
+ }
173
+ function safeRel(rel) {
174
+ const tokens = new Set((rel ?? "").split(/\s+/).filter(Boolean));
175
+ tokens.add("noopener");
176
+ tokens.add("noreferrer");
177
+ return [...tokens].join(" ");
178
+ }
179
+ var Link = forwardRef(LinkImpl);
180
+ var Code = forwardRef(function Code2({ className, ...props }, ref) {
181
+ return /* @__PURE__ */ jsx(
182
+ "code",
183
+ {
184
+ ref,
185
+ className: cn(
186
+ "rounded bg-muted px-[0.3em] py-[0.15em] font-mono text-[0.875em] text-foreground",
187
+ className
188
+ ),
189
+ ...props
190
+ }
191
+ );
192
+ });
193
+ var Kbd = forwardRef(function Kbd2({ className, ...props }, ref) {
194
+ return /* @__PURE__ */ jsx(
195
+ "kbd",
196
+ {
197
+ ref,
198
+ className: cn(
199
+ "rounded border border-border bg-muted px-1.5 py-0.5 font-mono text-xs font-medium text-foreground",
200
+ className
201
+ ),
202
+ ...props
203
+ }
204
+ );
205
+ });
11
206
 
12
207
  // src/Grid.tsx
13
- import { jsx, jsxs } from "react/jsx-runtime";
208
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
14
209
  function Grid({
15
210
  signal,
16
211
  columns,
@@ -19,11 +214,11 @@ function Grid({
19
214
  }) {
20
215
  const data = useSignal(signal);
21
216
  if (data.length === 0) {
22
- return /* @__PURE__ */ jsx("p", { style: { color: "#888", fontStyle: "italic" }, children: emptyMessage });
217
+ return /* @__PURE__ */ jsx2("p", { style: { color: "#888", fontStyle: "italic" }, children: emptyMessage });
23
218
  }
24
219
  const cols = columns ?? Object.keys(data[0]);
25
- return /* @__PURE__ */ jsxs("table", { style: { borderCollapse: "collapse", width: "100%" }, children: [
26
- /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsx("tr", { children: cols.map((col) => /* @__PURE__ */ jsx(
220
+ return /* @__PURE__ */ jsxs2("table", { style: { borderCollapse: "collapse", width: "100%" }, children: [
221
+ /* @__PURE__ */ jsx2("thead", { children: /* @__PURE__ */ jsx2("tr", { children: cols.map((col) => /* @__PURE__ */ jsx2(
27
222
  "th",
28
223
  {
29
224
  style: {
@@ -38,9 +233,9 @@ function Grid({
38
233
  },
39
234
  String(col)
40
235
  )) }) }),
41
- /* @__PURE__ */ jsx("tbody", { children: data.map((row, rowIndex) => (
236
+ /* @__PURE__ */ jsx2("tbody", { children: data.map((row, rowIndex) => (
42
237
  // biome-ignore lint/suspicious/noArrayIndexKey: row has no guaranteed unique ID at this layer
43
- /* @__PURE__ */ jsx("tr", { style: { backgroundColor: rowIndex % 2 === 0 ? "#fff" : "#f9fafb" }, children: cols.map((col) => /* @__PURE__ */ jsx(
238
+ /* @__PURE__ */ jsx2("tr", { style: { backgroundColor: rowIndex % 2 === 0 ? "#fff" : "#f9fafb" }, children: cols.map((col) => /* @__PURE__ */ jsx2(
44
239
  "td",
45
240
  {
46
241
  style: {
@@ -56,7 +251,39 @@ function Grid({
56
251
  )) })
57
252
  ] });
58
253
  }
254
+
255
+ // src/icons/create-icon-set.tsx
256
+ import { forwardRef as forwardRef2 } from "react";
257
+ import { jsx as jsx3 } from "react/jsx-runtime";
258
+ function createIconSet(icons) {
259
+ for (const [name, component] of Object.entries(icons)) assertIconEntry(name, component);
260
+ const own = Object.freeze({ ...icons });
261
+ const names = Object.freeze(Object.keys(own));
262
+ const SetIcon = forwardRef2(function SetIcon2({ name, ...props }, ref) {
263
+ const icon = Object.hasOwn(own, name) ? own[name] : void 0;
264
+ if (!icon) {
265
+ warnMissingIcon(name);
266
+ return null;
267
+ }
268
+ return /* @__PURE__ */ jsx3(Icon, { ref, icon, ...props });
269
+ });
270
+ return { Icon: SetIcon, names };
271
+ }
59
272
  export {
273
+ Button,
274
+ Code,
60
275
  Grid,
276
+ Heading,
277
+ Icon,
278
+ Input,
279
+ Kbd,
280
+ Link,
281
+ Spinner,
282
+ Text,
283
+ Typography,
284
+ buttonVariants,
285
+ cn,
286
+ createIconSet,
287
+ registerIcons,
61
288
  useSignal
62
289
  };
@@ -0,0 +1,14 @@
1
+ import * as react from 'react';
2
+ import { InputProps as InputProps$1 } from '@base-ui/react/input';
3
+
4
+ interface InputProps extends Omit<InputProps$1, "className"> {
5
+ className?: string;
6
+ }
7
+ /**
8
+ * A text input. `ref` is the real `<input>`, so `react-hook-form`'s `register()` works with
9
+ * no `Controller`. Height and horizontal padding follow the density tokens. Native `onChange`
10
+ * and the typed `onValueChange(value)` both fire.
11
+ */
12
+ declare const Input: react.ForwardRefExoticComponent<Omit<InputProps, "ref"> & react.RefAttributes<HTMLInputElement>>;
13
+
14
+ export { Input, type InputProps };
package/dist/input.js ADDED
@@ -0,0 +1,8 @@
1
+ "use client";
2
+ import {
3
+ Input
4
+ } from "./chunk-GX2YEJ43.js";
5
+ import "./chunk-2TQSHVXA.js";
6
+ export {
7
+ Input
8
+ };
@@ -0,0 +1,80 @@
1
+ import { c as ContainerSize, B as Breakpoint, G as Gap } from '../responsive-YJBnvsjt.js';
2
+ import 'react';
3
+
4
+ /**
5
+ * How MUI `Grid`, `Stack` and `Container` map to `@azmr/ui` layout components. Pure data and
6
+ * pure functions for the migration codemod, which rewrites what is exact and flags what returns
7
+ * `undefined` or `approximate`. Imports only types.
8
+ */
9
+ declare const muiLayoutMap: {
10
+ readonly grid: {
11
+ readonly container: "Use <Grid cols={12}>. It is a CSS grid, not MUI's flex-based container.";
12
+ readonly item: "Use <GridItem span={{ base, sm, md, lg, xl }}> with the same numbers.";
13
+ readonly props: {
14
+ readonly spacing: "gap (MUI unit 8px, ours 4px: spacing 2 is gap 4). See muiSpacingToGap.";
15
+ readonly rowSpacing: "No separate row gap: use gap, or className=\"gap-y-*\".";
16
+ readonly columnSpacing: "No separate column gap: use gap, or className=\"gap-x-*\".";
17
+ readonly direction: "Not needed: GridItem placement is by column span.";
18
+ readonly alignItems: "align";
19
+ readonly justifyContent: "justify (justifyItems semantics in a grid).";
20
+ readonly columns: "cols (the number of columns, default 12 in MUI).";
21
+ readonly xs: "GridItem span.base";
22
+ readonly sm: "GridItem span.sm";
23
+ readonly md: "GridItem span.md";
24
+ readonly lg: "GridItem span.lg";
25
+ readonly xl: "GridItem span.xl";
26
+ };
27
+ };
28
+ readonly stack: {
29
+ readonly props: {
30
+ readonly spacing: "gap (MUI unit 8px, ours 4px). See muiSpacingToGap.";
31
+ readonly direction: "direction (accepts a responsive object).";
32
+ readonly divider: "divider";
33
+ readonly alignItems: "align";
34
+ readonly justifyContent: "justify";
35
+ readonly useFlexGap: "Not needed: Stack always uses flex gap.";
36
+ };
37
+ };
38
+ readonly container: {
39
+ readonly props: {
40
+ readonly maxWidth: "size (see muiContainerSize).";
41
+ readonly disableGutters: "gutters={false}";
42
+ readonly fixed: "Not supported: use size.";
43
+ };
44
+ };
45
+ readonly breakpoints: {
46
+ readonly xs: "base";
47
+ readonly sm: "sm";
48
+ readonly md: "md";
49
+ readonly lg: "lg";
50
+ readonly xl: "xl";
51
+ readonly note: "MUI breakpoints are 0/600/900/1200/1536px; Tailwind's are 0/640/768/1024/1280px, so layouts shift a little near the boundaries. Check them in the browser.";
52
+ };
53
+ };
54
+ /** The gap step for a MUI `spacing` value, or `undefined` when there is no equivalent step. */
55
+ declare function muiSpacingToGap(spacing: number): Gap | undefined;
56
+ declare function muiBreakpoint(key: string): Breakpoint | undefined;
57
+ interface ContainerSizeTarget {
58
+ size: ContainerSize;
59
+ /** True when the width is only close, so the codemod should flag it. */
60
+ approximate?: true;
61
+ }
62
+ /** `maxWidth` of a MUI Container. `undefined` is MUI's default (`lg`); `false` removes the limit. */
63
+ declare function muiContainerSize(maxWidth: "xs" | "sm" | "md" | "lg" | "xl" | false | undefined): ContainerSizeTarget | undefined;
64
+ type MuiColumns = number | "auto" | boolean;
65
+ interface MuiGridItemSpan {
66
+ /** The responsive span for `GridItem`, or `undefined` when none of the props could be mapped. */
67
+ span: Partial<Record<Breakpoint, number>> | undefined;
68
+ /** Props that have no equivalent (`auto`, `true`, out of range), as `prop=value`, for flagging. */
69
+ unsupported: string[];
70
+ }
71
+ /** Converts MUI `Grid` item props (`xs`, `sm`, ...) to a `GridItem` span. */
72
+ declare function muiGridItemSpan(props: {
73
+ xs?: MuiColumns;
74
+ sm?: MuiColumns;
75
+ md?: MuiColumns;
76
+ lg?: MuiColumns;
77
+ xl?: MuiColumns;
78
+ }): MuiGridItemSpan;
79
+
80
+ export { type ContainerSizeTarget, type MuiGridItemSpan, muiBreakpoint, muiContainerSize, muiGridItemSpan, muiLayoutMap, muiSpacingToGap };