@sableui/react 0.4.0 → 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 (90) hide show
  1. package/AGENTS.md +2 -2
  2. package/CHANGELOG.md +189 -0
  3. package/CONTRIBUTING.md +1 -1
  4. package/THIRD_PARTY_NOTICES.md +11 -0
  5. package/bin/sable-lint.mjs +2 -1
  6. package/bin/sable.mjs +3 -2
  7. package/dist/{_contract-Cn3lUpih.d.ts → _contract-C2M1SjBf.d.ts} +20 -2
  8. package/dist/blocks/index.js +21 -53
  9. package/dist/{chunk-CCUDFLU3.js → chunk-7QSDYBXO.js} +652 -38
  10. package/dist/{chunk-FBSL2LZQ.js → chunk-EDXLM7YL.js} +11 -30
  11. package/dist/chunk-FKZXAFIY.js +12 -0
  12. package/dist/{chunk-OQACYT2D.js → chunk-NETUFI34.js} +23 -1
  13. package/dist/{chunk-NGBDP3BM.js → chunk-QJ6FWTUG.js} +1 -1
  14. package/dist/{chunk-D2ETQBHV.js → chunk-VVW4UCDI.js} +5 -5
  15. package/dist/{chunk-TH563WLW.js → chunk-XAZGMY73.js} +10 -3
  16. package/dist/foundations/index.js +6 -0
  17. package/dist/icon/index.js +2 -2
  18. package/dist/icon-sets/brands.d.ts +0 -27
  19. package/dist/icon-sets/brands.js +7 -1
  20. package/dist/icon-sets/reicon.js +1 -1
  21. package/dist/index.d.ts +164 -23
  22. package/dist/index.js +116 -29
  23. package/dist/ios/index.d.ts +6 -1
  24. package/dist/ios/index.js +4 -3
  25. package/dist/ios/styles.css +9 -0
  26. package/dist/patterns/index.js +24 -30
  27. package/dist/presets/index.d.ts +108 -5
  28. package/dist/presets/index.js +239 -6
  29. package/dist/styles.css +57 -0
  30. package/dist/{theme-provider-CGeiusgu.d.ts → theme-provider-kQszHYji.d.ts} +1 -1
  31. package/dist/themes/atelier/atelier.css +31 -3
  32. package/dist/themes/atelier/index.d.ts +1 -1
  33. package/dist/themes/ember/ember.css +38 -7
  34. package/dist/themes/ember/index.d.ts +1 -1
  35. package/dist/themes/index.d.ts +2 -2
  36. package/dist/themes/meridian/index.d.ts +1 -1
  37. package/dist/themes/meridian/meridian.css +33 -4
  38. package/dist/themes/poppy/index.d.ts +1 -1
  39. package/dist/themes/poppy/poppy.css +28 -0
  40. package/dist/themes/prism/index.d.ts +1 -1
  41. package/dist/themes/prism/prism.css +26 -0
  42. package/dist/themes/sable/index.d.ts +1 -1
  43. package/dist/themes/sable/sable.css +24 -11
  44. package/dist/themes/verdant/index.d.ts +1 -1
  45. package/dist/themes/verdant/verdant.css +34 -4
  46. package/llms/blocks/danger-zone-block.md +1 -1
  47. package/llms/blocks/event-card-block.md +1 -1
  48. package/llms/blocks/feedback-form-block.md +1 -1
  49. package/llms/blocks/invite-team-block.md +1 -1
  50. package/llms/blocks/media-player-block.md +3 -16
  51. package/llms/blocks/notification-list-block.md +3 -3
  52. package/llms/blocks/product-card-block.md +3 -17
  53. package/llms/blocks/profile-card-block.md +4 -17
  54. package/llms/blocks/profile-form-block.md +2 -2
  55. package/llms/blocks/team-members-block.md +1 -1
  56. package/llms/blocks/testimonial-block.md +1 -1
  57. package/llms/components/avatar.md +13 -1
  58. package/llms/components/card.md +1 -1
  59. package/llms/components/gradient-art.md +80 -0
  60. package/llms/components/sheet.md +1 -1
  61. package/llms/components/tabs.md +1 -1
  62. package/llms/components/toast.md +12 -1
  63. package/llms/foundations/accessibility.md +1 -0
  64. package/llms/patterns/auth-page.md +5 -19
  65. package/llms/patterns/brand-landing-page.md +1 -1
  66. package/llms/patterns/chat-panel.md +1 -1
  67. package/llms/patterns/dashboard-page.md +4 -4
  68. package/llms/patterns/feed-page.md +4 -4
  69. package/llms/patterns/landing-page.md +1 -1
  70. package/llms/patterns/list-detail-page.md +3 -2
  71. package/llms/patterns/settings-page.md +3 -3
  72. package/llms/reference/token-intent.md +9 -1
  73. package/llms/tasks/auditing-an-app.md +6 -0
  74. package/llms/tasks/building-an-ios-prototype.md +3 -1
  75. package/llms/tasks/converting-an-app.md +1 -1
  76. package/llms/tasks/creating-a-preset.md +24 -0
  77. package/llms/tasks/reviewing-a-design.md +9 -0
  78. package/llms/tasks/using-presets.md +6 -1
  79. package/llms-full.txt +214 -106
  80. package/llms.txt +4 -3
  81. package/package.json +9 -7
  82. package/registry.json +310 -32
  83. package/scripts/design-presets.mjs +27 -4
  84. package/scripts/grade.mjs +2 -1
  85. package/scripts/label-contrast.mjs +138 -0
  86. package/scripts/lint-rules.mjs +23 -2
  87. package/skills/sable/SKILL.md +3 -1
  88. package/targets/ios.json +18 -2
  89. package/third-party/paper-shaders-LICENSE.txt +201 -0
  90. package/third-party/paper-shaders-NOTICE.txt +5 -0
@@ -1,8 +1,8 @@
1
- import { FIELD_SHELL, FIELD_INVALID, useMotion, useTypeTier, useScrollActivity, setRef, useAnchoredDensity, Dialog, DialogContent, DialogTitle, DialogDescription, useIsomorphicLayoutEffect } from './chunk-CCUDFLU3.js';
1
+ import { FIELD_SHELL, FIELD_INVALID, useMotion, useTypeTier, useScrollActivity, setRef, useEdgeFade, useAnchoredDensity, Dialog, DialogContent, DialogTitle, DialogDescription, useIsomorphicLayoutEffect } from './chunk-7QSDYBXO.js';
2
2
  import { cn } from './chunk-SRQWQUTW.js';
3
- import { Icon } from './chunk-NGBDP3BM.js';
3
+ import { Icon } from './chunk-QJ6FWTUG.js';
4
4
  import * as OtpParts from '@base-ui/react/otp-field';
5
- import { createContext, Fragment, useRef, useState, useId, useEffect, Children, isValidElement, useContext, useCallback, useLayoutEffect, useSyncExternalStore, useMemo } from 'react';
5
+ import { createContext, Fragment, useRef, useState, useId, useEffect, Children, isValidElement, useContext, useCallback, useSyncExternalStore, useMemo } from 'react';
6
6
  import { jsx, jsxs, Fragment as Fragment$1 } from 'react/jsx-runtime';
7
7
  import { Checkbox as Checkbox$1 } from '@base-ui/react/checkbox';
8
8
  import { cva } from 'class-variance-authority';
@@ -2652,8 +2652,9 @@ function Sparkline({ data, label, variant = "line", tone = "primary", animate =
2652
2652
  const [ref, inView] = useArrival();
2653
2653
  const shown = !animate || !enabled || inView;
2654
2654
  const color = toneColor(tone);
2655
- const lo = Math.min(0, ...data);
2656
- const hi = Math.max(...data, lo + 1);
2655
+ const min = data.length ? Math.min(...data) : 0;
2656
+ const max = data.length ? Math.max(...data) : 1;
2657
+ const [lo, hi] = variant === "bar" ? [Math.min(0, min), Math.max(max, Math.min(0, min) + 1)] : min === max ? [min - 1, max + 1] : [min, max];
2657
2658
  const y = (v) => H - 2 - (v - lo) / (hi - lo) * (H - 4);
2658
2659
  const nf = new Intl.NumberFormat(locale, { maximumFractionDigits: 2 });
2659
2660
  const summary = data.length ? `${label}: from ${nf.format(data[0])} to ${nf.format(data[data.length - 1])}, low ${nf.format(Math.min(...data))}, high ${nf.format(Math.max(...data))}` : label;
@@ -3775,7 +3776,7 @@ function SliderThumb({ className, children, ...props }) {
3775
3776
  {
3776
3777
  "aria-hidden": true,
3777
3778
  className: cn(
3778
- "pointer-events-none absolute inset-0 rounded-full border-2 border-primary bg-background shadow-sm",
3779
+ "pointer-events-none absolute inset-0 rounded-full border-2 border-primary bg-background shadow-(--knob-shadow)",
3779
3780
  // The only thing that resizes. Scale (not width/height) so the box
3780
3781
  // metrics — and the row height around them — never move.
3781
3782
  "scale-75 motion-interactive ease-spring",
@@ -4225,35 +4226,15 @@ function Scroller({
4225
4226
  },
4226
4227
  [onKeyDown, orientation]
4227
4228
  );
4228
- const [showStart, setShowStart] = useState(false);
4229
- const [showEnd, setShowEnd] = useState(false);
4230
- const sync = useCallback(
4231
- (el) => {
4232
- if (orientation === "horizontal") {
4233
- const { scrollLeft, scrollWidth, clientWidth } = el;
4234
- setShowStart(scrollLeft > 0);
4235
- setShowEnd(scrollLeft < scrollWidth - clientWidth - 1);
4236
- } else {
4237
- const { scrollTop, scrollHeight, clientHeight } = el;
4238
- setShowStart(scrollTop > 0);
4239
- setShowEnd(scrollTop < scrollHeight - clientHeight - 1);
4240
- }
4241
- },
4242
- [orientation]
4243
- );
4244
- useLayoutEffect(() => {
4245
- if (regionRef.current) sync(regionRef.current);
4246
- }, [sync]);
4229
+ const { sync: syncFade, style: fadeStyle } = useEdgeFade(regionRef, orientation);
4247
4230
  const handleScroll = useCallback(
4248
4231
  (event) => {
4249
- sync(event.currentTarget);
4232
+ syncFade();
4250
4233
  onScroll?.(event);
4251
4234
  },
4252
- [sync, onScroll]
4235
+ [syncFade, onScroll]
4253
4236
  );
4254
4237
  const isVertical = orientation === "vertical";
4255
- const fade = "calc(var(--spacing) * 7)";
4256
- const mask = showStart || showEnd ? `linear-gradient(to ${isVertical ? "bottom" : "right"}, ${showStart ? "transparent" : "#000"}, #000 ${showStart ? fade : "0"}, #000 ${showEnd ? `calc(100% - ${fade})` : "100%"}, ${showEnd ? "transparent" : "#000"})` : void 0;
4257
4238
  return (
4258
4239
  // The chrome box. Carries the consumer's border/background/radius and the
4259
4240
  // sizing, and is NOT masked — which is the entire point of the split. A
@@ -4269,7 +4250,7 @@ function Scroller({
4269
4250
  role: "group",
4270
4251
  "aria-label": label,
4271
4252
  "data-orientation": orientation,
4272
- style: mask ? { maskImage: mask, WebkitMaskImage: mask } : void 0,
4253
+ style: fadeStyle,
4273
4254
  className: cn(
4274
4255
  // Fill the chrome box without a percentage height. `min-h-0` /
4275
4256
  // `min-w-0` because a flex item's default `min-size: auto` refuses to
@@ -0,0 +1,12 @@
1
+ import { createContext, useContext } from 'react';
2
+
3
+ // src/lib/presentation.tsx
4
+ var PresentationContext = createContext("page");
5
+ var PresentationProvider = PresentationContext.Provider;
6
+ function usePresentation() {
7
+ return useContext(PresentationContext);
8
+ }
9
+ var CardDepthContext = createContext(0);
10
+ var StackedActionsContext = createContext(false);
11
+
12
+ export { CardDepthContext, PresentationProvider, StackedActionsContext, usePresentation };
@@ -54,6 +54,16 @@ var SEMANTIC_TOKENS = [
54
54
  "tone-info-foreground",
55
55
  "tone-warning-foreground",
56
56
  "highlight-foreground",
57
+ // Status text — a status colour drawn ON a surface: text, icons, borders,
58
+ // rings. Separate from the fill because the two want different lightness in
59
+ // dark mode: a solid fill sits low enough for a white label, while text and
60
+ // marks must stay light enough to read on a dark card. `text-destructive`,
61
+ // `border-destructive` and `ring-destructive` read these through Tailwind's
62
+ // per-property colour namespaces (styles.css); only `bg-*` reads the fill.
63
+ "destructive-text",
64
+ "success-text",
65
+ "tone-warning-text",
66
+ "tone-info-text",
57
67
  // Overlay — a fixed, theme-independent dark surface for things that sit OVER
58
68
  // content rather than on a theme surface: modal/sheet scrims, media letterbox,
59
69
  // pills on imagery. `overlay-foreground` is its always-legible light ink.
@@ -278,6 +288,18 @@ var WORKSPACE_SURFACE_TOKENS = [
278
288
  "hairline",
279
289
  "hairline-strong"
280
290
  ];
291
+ var ART_TOKENS = [
292
+ "art-1",
293
+ "art-2",
294
+ "art-3",
295
+ "art-4",
296
+ "art-5",
297
+ "art-6",
298
+ "art-ground",
299
+ "art-warp",
300
+ "art-softness",
301
+ "art-grain"
302
+ ];
281
303
  var DERIVED_EDGE_TOKENS = ["border-floating"];
282
304
  var TYPE_UI_TOKENS = [
283
305
  "type-ui-md-size",
@@ -290,4 +312,4 @@ var TYPE_UI_TOKENS = [
290
312
  "type-ui-micro-weight"
291
313
  ];
292
314
 
293
- export { DENSITY_TOKENS, DERIVED_EDGE_TOKENS, LAYERING_TOKENS, MOTION_TOKENS, RADIUS_TOKENS, SEMANTIC_TOKENS, TYPE_OVERLINE_TOKENS, TYPE_REFINEMENT_TOKENS, TYPE_SCALE_TOKENS, TYPE_UI_TOKENS, WORKSPACE_SURFACE_TOKENS };
315
+ export { ART_TOKENS, DENSITY_TOKENS, DERIVED_EDGE_TOKENS, LAYERING_TOKENS, MOTION_TOKENS, RADIUS_TOKENS, SEMANTIC_TOKENS, TYPE_OVERLINE_TOKENS, TYPE_REFINEMENT_TOKENS, TYPE_SCALE_TOKENS, TYPE_UI_TOKENS, WORKSPACE_SURFACE_TOKENS };
@@ -1,4 +1,4 @@
1
- import { reiconIconSet } from './chunk-TH563WLW.js';
1
+ import { reiconIconSet } from './chunk-XAZGMY73.js';
2
2
  import { createContext, useMemo, useContext } from 'react';
3
3
  import { jsx, Fragment } from 'react/jsx-runtime';
4
4
 
@@ -1,6 +1,6 @@
1
- import { useMotion, useIsomorphicLayoutEffect, mergeRefs, trimLabel, useTypeTier, buttonVariants, Input, Table, TableCaption, TableHeader, TableRow, TableHead, Button, TableBody, TableCell, Card, SimpleTooltip, useDensity, FIELD_SHELL, FIELD_INVALID, MOBILE_FIELD_TIER, Tooltip, TooltipTrigger, TooltipContent, useScrollActivity, setRef, Textarea, Menu, MenuTrigger, MenuContent, MenuSubmenu, MenuSubmenuTrigger, Separator } from './chunk-CCUDFLU3.js';
1
+ import { useMotion, useIsomorphicLayoutEffect, mergeRefs, trimLabel, useTypeTier, buttonVariants, Input, Table, TableCaption, TableHeader, TableRow, TableHead, Button, TableBody, TableCell, Card, SimpleTooltip, useDensity, FIELD_SHELL, FIELD_INVALID, MOBILE_FIELD_TIER, Tooltip, TooltipTrigger, TooltipContent, useScrollActivity, setRef, Textarea, Menu, MenuTrigger, MenuContent, MenuSubmenu, MenuSubmenuTrigger, Separator } from './chunk-7QSDYBXO.js';
2
2
  import { cn } from './chunk-SRQWQUTW.js';
3
- import { Icon } from './chunk-NGBDP3BM.js';
3
+ import { Icon } from './chunk-QJ6FWTUG.js';
4
4
  import { createContext, useRef, useState, useEffect, isValidElement, cloneElement, useContext, useMemo, useCallback, useImperativeHandle } from 'react';
5
5
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
6
6
  import { flushSync } from 'react-dom';
@@ -286,8 +286,8 @@ function TabsTrigger({ className, children, ...props }) {
286
286
  variant === "underline" ? (
287
287
  // On the control ladder like the pill variant (it was py-2 plus
288
288
  // the label's line, ~36px — no rung).
289
- "-mb-px inline-flex h-(--control-md) items-center border-b-2 border-transparent px-3 data-[active]:border-foreground"
290
- ) : "inline-flex h-(--control-sm) items-center rounded-sm px-3 data-[active]:bg-muted",
289
+ "-mb-px inline-flex h-(--control-md) items-center gap-(--control-gap) border-b-2 border-transparent px-3 data-[active]:border-foreground"
290
+ ) : "inline-flex h-(--control-sm) items-center gap-(--control-gap) rounded-[var(--button-radius,9999px)] px-3 data-[active]:bg-muted",
291
291
  className
292
292
  ),
293
293
  ...props,
@@ -385,7 +385,7 @@ var tabsMeta = {
385
385
  {
386
386
  name: "TabsList",
387
387
  type: 'Base UI Tabs.List props (activateOnFocus, loopFocus) + variant?: "underline" | "pill" + className',
388
- description: 'The tablist row. variant="underline" (default) draws a divider rule beneath the triggers; variant="pill" drops the rule and fills the active trigger. Triggers inherit the variant.'
388
+ description: `The tablist row. variant="underline" (default) draws a divider rule beneath the triggers; variant="pill" drops the rule and fills the active trigger, which takes the theme's button shape (--button-radius). Triggers inherit the variant.`
389
389
  },
390
390
  {
391
391
  name: "TabsTrigger",
@@ -69,6 +69,7 @@ import { Send } from 'reicon-react/icons/Send';
69
69
  import { Star } from 'reicon-react/icons/Star';
70
70
  import { Trash } from 'reicon-react/icons/Trash';
71
71
  import { Upload } from 'reicon-react/icons/Upload';
72
+ import { memo } from 'react';
72
73
  import { jsx } from 'react/jsx-runtime';
73
74
 
74
75
  // src/icon-sets/reicon.tsx
@@ -165,16 +166,22 @@ var reiconIconSet = ({
165
166
  if (!Glyph) return null;
166
167
  const a11y = title ? { role: "img", "aria-label": title } : { "aria-hidden": true };
167
168
  return /* @__PURE__ */ jsx(
168
- Glyph,
169
+ ReiconGlyph,
169
170
  {
170
- size: "1em",
171
+ glyph: Glyph,
171
172
  weight: WEIGHTS[variant] ?? "Outline",
172
173
  className: spin ? `motion-spin ${className ?? ""}` : className,
173
- style: { color: void 0 },
174
174
  ...a11y
175
175
  }
176
176
  );
177
177
  };
178
+ var NO_INLINE_COLOR = { color: void 0 };
179
+ var ReiconGlyph = memo(function ReiconGlyph2({
180
+ glyph: Glyph,
181
+ ...props
182
+ }) {
183
+ return /* @__PURE__ */ jsx(Glyph, { size: "1em", style: NO_INLINE_COLOR, ...props });
184
+ });
178
185
  var reiconIconNames = Object.keys(ICONS);
179
186
 
180
187
  export { reiconIconNames, reiconIconSet };
@@ -63,6 +63,12 @@ var accessibility = {
63
63
  why: "A faded ring loses the contrast the theme tested.",
64
64
  enforcedBy: "sable-lint: faded-focus-ring"
65
65
  },
66
+ {
67
+ never: "A brand or status fill retuned under its old label \u2014 dark ink on a bright red that passes 4.5:1 at APCA Lc 42.",
68
+ instead: "A label that clears 4.5:1 and APCA Lc 60 in both modes. Move the fill's lightness, not its hue, keeping the ink its colour takes. A status colour on a surface is its own token (`--destructive-text`), so the fill can move freely.",
69
+ why: "The ratio alone passes labels that read muddy. A deliberate brand pair is allowed with a recorded reason (lint disable or preset exceptions).",
70
+ enforcedBy: "sable-lint: label-contrast"
71
+ },
66
72
  {
67
73
  never: 'Blocking paste, or type="number" for codes and card numbers.',
68
74
  instead: 'type="text" inputMode="numeric" with the right autocomplete.',
@@ -1,2 +1,2 @@
1
- export { Icon, IconProvider, composeIconSets, useIconSet } from '../chunk-NGBDP3BM.js';
2
- export { reiconIconSet as fallbackIconSet, reiconIconNames, reiconIconSet } from '../chunk-TH563WLW.js';
1
+ export { Icon, IconProvider, composeIconSets, useIconSet } from '../chunk-QJ6FWTUG.js';
2
+ export { reiconIconSet as fallbackIconSet, reiconIconNames, reiconIconSet } from '../chunk-XAZGMY73.js';
@@ -10,33 +10,6 @@ interface BrandGlyph {
10
10
  declare const BRAND_GRID = 24;
11
11
  declare const BRAND_GLYPHS: Record<string, BrandGlyph>;
12
12
 
13
- /**
14
- * Brand marks as a Sable icon set — `<Icon name="github" />`.
15
- *
16
- * This is an ADDITIVE set: it answers only for the brands it carries and
17
- * returns `null` for everything else, which is exactly what `composeIconSets`
18
- * falls through on. So it layers under a UI set rather than replacing one:
19
- *
20
- * <IconProvider set={composeIconSets(brandIconSet, reiconIconSet)} />
21
- *
22
- * Order matters only if a name collides. None do today — the brand names are
23
- * proper nouns (`github`, `figma`) and the contract's names are common ones
24
- * (`gear`, `chevron-down`) — but put the brand set first if you ever want a
25
- * brand to win.
26
- *
27
- * **Marks are monochrome by default and take the surrounding ink**, because
28
- * that is what a footer social row wants and it keeps rule #1 intact: nothing
29
- * here names a color, so `text-muted-foreground` on the icon governs. The
30
- * generator strips upstream `fill`/`stroke` colors for this reason. A brand
31
- * that must appear in its official color is a deliberate act at the call site —
32
- * a token, or an arbitrary color utility on that one instance — never a
33
- * default. A page where every logo asserts its own brand color is how a footer
34
- * turns into a fruit salad.
35
- *
36
- * The glyph data is vendored and committed, never fetched at render time; see
37
- * `scripts/fetch-brand-icons.mjs` for why. Trademark note: these designs belong
38
- * to their owners — follow each brand's usage guidelines.
39
- */
40
13
  declare const brandIconSet: IconSet;
41
14
  /** The brand names this set answers to — useful for a coverage assertion. */
42
15
  declare const brandIconNames: string[];
@@ -119,6 +119,12 @@ var BRAND_GLYPHS = {
119
119
  markup: '<path d="M15.337 23.979l7.216-1.561s-2.604-17.613-2.625-17.73c-.018-.116-.114-.192-.211-.192s-1.929-.136-1.929-.136-1.275-1.274-1.439-1.411c-.045-.037-.075-.057-.121-.074l-.914 21.104h.023zM11.71 11.305s-.81-.424-1.774-.424c-1.447 0-1.504.906-1.504 1.141 0 1.232 3.24 1.715 3.24 4.629 0 2.295-1.44 3.76-3.406 3.76-2.354 0-3.54-1.465-3.54-1.465l.646-2.086s1.245 1.066 2.28 1.066c.675 0 .975-.545.975-.932 0-1.619-2.654-1.694-2.654-4.359-.034-2.237 1.571-4.416 4.827-4.416 1.257 0 1.875.361 1.875.361l-.945 2.715-.02.01zM11.17.83c.136 0 .271.038.405.135-.984.465-2.064 1.639-2.508 3.992-.656.213-1.293.405-1.889.578C7.697 3.75 8.951.84 11.17.84V.83zm1.235 2.949v.135c-.754.232-1.583.484-2.394.736.466-1.777 1.333-2.645 2.085-2.971.193.501.309 1.176.309 2.1zm.539-2.234c.694.074 1.141.867 1.429 1.755-.349.114-.735.231-1.158.366v-.252c0-.752-.096-1.371-.271-1.871v.002zm2.992 1.289c-.02 0-.06.021-.078.021s-.289.075-.714.21c-.423-1.233-1.176-2.37-2.508-2.37h-.115C12.135.209 11.669 0 11.265 0 8.159 0 6.675 3.877 6.21 5.846c-1.194.365-2.063.636-2.16.674-.675.213-.694.232-.772.87-.075.462-1.83 14.063-1.83 14.063L15.009 24l.927-21.166z"/>'
120
120
  }
121
121
  };
122
+ var MARKUP = /* @__PURE__ */ new WeakMap();
123
+ function markupOf(glyph) {
124
+ let markup = MARKUP.get(glyph);
125
+ if (!markup) MARKUP.set(glyph, markup = { __html: glyph.markup });
126
+ return markup;
127
+ }
122
128
  var brandIconSet = ({
123
129
  name,
124
130
  spin,
@@ -137,7 +143,7 @@ var brandIconSet = ({
137
143
  height: "1em",
138
144
  fill: "currentColor",
139
145
  className: spin ? `motion-spin ${className ?? ""}` : className,
140
- dangerouslySetInnerHTML: { __html: glyph.markup },
146
+ dangerouslySetInnerHTML: markupOf(glyph),
141
147
  ...a11y
142
148
  }
143
149
  );
@@ -1 +1 @@
1
- export { reiconIconNames, reiconIconSet } from '../chunk-TH563WLW.js';
1
+ export { reiconIconNames, reiconIconSet } from '../chunk-XAZGMY73.js';