@allxsmith/bestax-bulma 5.66.2 → 5.67.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/dist/bestax.css +1 -1
  2. package/dist/bestax.css.map +1 -1
  3. package/dist/esm/components/Command.js.map +1 -1
  4. package/dist/esm/components/Dropdown.js +8 -2
  5. package/dist/esm/components/Dropdown.js.map +1 -1
  6. package/dist/esm/components/HoverCard.js.map +1 -1
  7. package/dist/esm/components/Loading.js +3 -3
  8. package/dist/esm/components/Loading.js.map +1 -1
  9. package/dist/esm/components/Modal.js.map +1 -1
  10. package/dist/esm/components/Popover.js.map +1 -1
  11. package/dist/esm/components/Sidebar.js +21 -29
  12. package/dist/esm/components/Sidebar.js.map +1 -1
  13. package/dist/esm/components/Toast.js +6 -8
  14. package/dist/esm/components/Toast.js.map +1 -1
  15. package/dist/esm/elements/IconButton.js.map +1 -1
  16. package/dist/esm/form/Combobox.js.map +1 -1
  17. package/dist/esm/form/Control.js +2 -5
  18. package/dist/esm/form/Control.js.map +1 -1
  19. package/dist/esm/form/DateInputBase.js.map +1 -1
  20. package/dist/esm/form/DateRangeInputBase.js.map +1 -1
  21. package/dist/esm/form/DateTimeInputBase.js.map +1 -1
  22. package/dist/esm/form/Field.js +2 -4
  23. package/dist/esm/form/Field.js.map +1 -1
  24. package/dist/esm/form/TreeSelect.js.map +1 -1
  25. package/dist/esm/form/_pickerInternals/Calendar.js +12 -5
  26. package/dist/esm/form/_pickerInternals/Calendar.js.map +1 -1
  27. package/dist/esm/form/_pickerInternals/PickerPopover.js +6 -2
  28. package/dist/esm/form/_pickerInternals/PickerPopover.js.map +1 -1
  29. package/dist/esm/helpers/scrollLock.js +47 -11
  30. package/dist/esm/helpers/scrollLock.js.map +1 -1
  31. package/dist/esm/helpers/useAnchoredPosition.js +35 -11
  32. package/dist/esm/helpers/useAnchoredPosition.js.map +1 -1
  33. package/dist/esm/layout/Level.js +2 -2
  34. package/dist/esm/layout/Level.js.map +1 -1
  35. package/dist/extras.css +1 -1
  36. package/dist/extras.css.map +1 -1
  37. package/dist/index.cjs +139 -75
  38. package/dist/index.cjs.map +1 -1
  39. package/dist/types/components/Command.d.ts +5 -5
  40. package/dist/types/components/Dropdown.d.ts +5 -1
  41. package/dist/types/components/HoverCard.d.ts +2 -4
  42. package/dist/types/components/Modal.d.ts +6 -3
  43. package/dist/types/components/Popover.d.ts +1 -3
  44. package/dist/types/components/Sidebar.d.ts +6 -2
  45. package/dist/types/components/Toast.d.ts +3 -1
  46. package/dist/types/elements/IconButton.d.ts +2 -5
  47. package/dist/types/form/Combobox.d.ts +13 -13
  48. package/dist/types/form/DateInputBase.d.ts +8 -1
  49. package/dist/types/form/DateRangeInputBase.d.ts +5 -0
  50. package/dist/types/form/DateTimeInputBase.d.ts +8 -1
  51. package/dist/types/form/TreeSelect.d.ts +4 -4
  52. package/dist/types/helpers/scrollLock.d.ts +4 -4
  53. package/dist/types/helpers/useAnchoredPosition.d.ts +14 -12
  54. package/dist/types/layout/Level.d.ts +10 -0
  55. package/dist/types-cjs/components/Command.d.ts +5 -5
  56. package/dist/types-cjs/components/Dropdown.d.ts +5 -1
  57. package/dist/types-cjs/components/HoverCard.d.ts +2 -4
  58. package/dist/types-cjs/components/Modal.d.ts +6 -3
  59. package/dist/types-cjs/components/Popover.d.ts +1 -3
  60. package/dist/types-cjs/components/Sidebar.d.ts +6 -2
  61. package/dist/types-cjs/components/Toast.d.ts +3 -1
  62. package/dist/types-cjs/elements/IconButton.d.ts +2 -5
  63. package/dist/types-cjs/form/Combobox.d.ts +13 -13
  64. package/dist/types-cjs/form/DateInputBase.d.ts +8 -1
  65. package/dist/types-cjs/form/DateRangeInputBase.d.ts +5 -0
  66. package/dist/types-cjs/form/DateTimeInputBase.d.ts +8 -1
  67. package/dist/types-cjs/form/TreeSelect.d.ts +4 -4
  68. package/dist/types-cjs/helpers/scrollLock.d.ts +4 -4
  69. package/dist/types-cjs/helpers/useAnchoredPosition.d.ts +14 -12
  70. package/dist/types-cjs/layout/Level.d.ts +10 -0
  71. package/dist/versions/bestax-no-dark-mode.css +1 -1
  72. package/dist/versions/bestax-no-dark-mode.css.map +1 -1
  73. package/dist/versions/bestax-no-helpers-prefixed.css +1 -1
  74. package/dist/versions/bestax-no-helpers-prefixed.css.map +1 -1
  75. package/dist/versions/bestax-no-helpers.css +1 -1
  76. package/dist/versions/bestax-no-helpers.css.map +1 -1
  77. package/dist/versions/bestax-prefixed.css +1 -1
  78. package/dist/versions/bestax-prefixed.css.map +1 -1
  79. package/package.json +1 -1
  80. package/src/scss/components/_loading.scss +17 -3
  81. package/src/scss/form/_radio.scss +5 -2
@@ -31,14 +31,16 @@ const samePosition = (a, b) => a.position === b.position &&
31
31
  /**
32
32
  * Places a floating panel against its anchor: resolves `auto` to a corner
33
33
  * and, for a panel fixed to the viewport, works out its coordinates. It
34
- * measures again on resize and on any scroll of the anchor's window (an
35
- * iframe's, when the anchor renders into one), so a fixed panel follows its
36
- * anchor, and with `followContent` after each render too. A measurement that
37
- * changes nothing doesn't render again.
34
+ * measures again on resize, on any scroll of the anchor's window (an
35
+ * iframe's, when the anchor renders into one), and when the panel or the
36
+ * anchor changes size, so a fixed panel follows its anchor and its own
37
+ * content. Those measure once in the next frame, however many arrive before
38
+ * it. With `followContent` it also measures after each render. A
39
+ * measurement that changes nothing doesn't render again.
38
40
  *
39
- * Measuring happens in a layout effect, so the panel is placed before it
40
- * paints. It needs both elements on the page while `active` is on, and
41
- * keeps the last placement when either is missing.
41
+ * The first measurement happens in a layout effect, so the panel is placed
42
+ * before it paints. It needs both elements on the page while `active` is
43
+ * on, and keeps the last placement when either is missing.
42
44
  *
43
45
  * @function useAnchoredPosition
44
46
  * @param anchorRef - The element the panel opens from.
@@ -95,12 +97,34 @@ function useAnchoredPosition(anchorRef, panelRef, { active, position, fixed, off
95
97
  };
96
98
  updateRef.current = update;
97
99
  update();
98
- view.addEventListener('resize', update, { passive: true });
99
- view.addEventListener('scroll', update, { passive: true, capture: true });
100
+ // A scroll, a resize or a change in size measures in the next frame,
101
+ // once however many of them ask.
102
+ let frame = 0;
103
+ const schedule = () => {
104
+ if (frame)
105
+ return;
106
+ frame = view.requestAnimationFrame(() => {
107
+ frame = 0;
108
+ update();
109
+ });
110
+ };
111
+ view.addEventListener('resize', schedule, { passive: true });
112
+ view.addEventListener('scroll', schedule, { passive: true, capture: true });
113
+ // The panel's content can change size without the component holding the
114
+ // hook rendering, as an image loading or a child's own state does, and
115
+ // so can the anchor.
116
+ const Observer = view.ResizeObserver;
117
+ const resizes = typeof Observer === 'undefined' ? null : new Observer(schedule);
118
+ for (const element of [anchorRef.current, panelRef.current]) {
119
+ if (element)
120
+ resizes?.observe(element);
121
+ }
100
122
  return () => {
101
123
  updateRef.current = null;
102
- view.removeEventListener('resize', update);
103
- view.removeEventListener('scroll', update, { capture: true });
124
+ view.cancelAnimationFrame(frame);
125
+ resizes?.disconnect();
126
+ view.removeEventListener('resize', schedule);
127
+ view.removeEventListener('scroll', schedule, { capture: true });
104
128
  };
105
129
  }, [
106
130
  active,
@@ -1 +1 @@
1
- {"version":3,"file":"useAnchoredPosition.js","sources":["../../../src/helpers/useAnchoredPosition.ts"],"sourcesContent":["// INTERNAL: deliberately not exported from src/index.ts.\nimport { useRef, useState } from 'react';\nimport type { RefObject } from 'react';\nimport type { PickerPosition } from '../form/_pickerInternals/pickerTypes';\nimport { useClientLayoutEffect } from './useClientLayoutEffect';\n\n/** A corner of the anchor the panel opens from, once `auto` is resolved. */\nexport type AnchoredCorner = Exclude<PickerPosition, 'auto'>;\n\n/**\n * Where the panel goes: the corner it opens from and, when it is fixed to\n * the viewport, its coordinates there.\n */\nexport interface AnchoredPosition {\n position: AnchoredCorner;\n top?: number;\n left?: number;\n /**\n * With `matchWidth`, the anchor's width, which a fixed panel takes as its\n * `min-width`.\n */\n minWidth?: number;\n}\n\n/**\n * Options for `useAnchoredPosition`.\n */\nexport interface UseAnchoredPositionOptions {\n /** Whether the panel is on the page. Nothing is measured while it is not. */\n active: boolean;\n /**\n * The corner asked for, or `auto` to pick one that keeps the panel in the\n * viewport. A named corner is physical, whatever the page's direction.\n * Left out, the corner is `bottom-left` lined up with the anchor's inline\n * start, which is its right edge right to left. A panel in place gets that\n * from its stylesheet, as Popover's and the pickers' do; a fixed panel's\n * coordinates read the anchor's direction.\n */\n position?: PickerPosition;\n /**\n * Whether the panel is fixed to the viewport (it was portaled away from the\n * anchor), which needs coordinates. Otherwise the panel's CSS places it\n * against the anchor from the corner alone.\n */\n fixed: boolean;\n /**\n * The gap between the anchor and the panel, in pixels, that the hook puts\n * there itself: added to the fixed coordinates and to the room `auto` asks\n * for below the anchor. Popover and the pickers' popover pass `0` and take\n * their gap from a margin in their stylesheet, read through `styledGap`, so\n * a theme's offset moves the panel and `auto` alike. A new panel should do\n * the same rather than rely on this default, which no stylesheet sees.\n * @defaultValue 4\n */\n offset?: number;\n /**\n * Reads the gap the panel's own stylesheet puts between it and the anchor,\n * in pixels, each time the panel is measured. `auto` leaves room for it as\n * well; the coordinates don't include it, because the stylesheet applies it.\n */\n styledGap?: (panel: HTMLElement) => number;\n /**\n * Whether the panel is at least as wide as the anchor, as a list under its\n * field is. A panel in place gets that from its stylesheet. A fixed one\n * can't, so its placement carries the anchor's width as `minWidth` for the\n * panel to set, and its coordinates and `auto` already allow for it.\n * @defaultValue false\n */\n matchWidth?: boolean;\n /**\n * Measures again after each render of the component holding the hook, for\n * a panel whose content changes while it's open, as a filtered list's\n * does. A fixed panel above its anchor is placed from its height, and\n * `auto` reads the height too, so a measurement taken when it opened goes\n * stale as the content changes.\n * @defaultValue false\n */\n followContent?: boolean;\n}\n\n/**\n * A `styledGap` for a panel whose stylesheet puts the gap in a margin on the\n * side facing the anchor, negative on a portaled panel above it, so the\n * larger magnitude is the gap. In pixels.\n */\nexport function marginGap(panel: HTMLElement): number {\n const { marginTop, marginBottom } = getComputedStyle(panel);\n return Math.max(\n Math.abs(parseFloat(marginTop)) || 0,\n Math.abs(parseFloat(marginBottom)) || 0\n );\n}\n\n/**\n * The corner that keeps a panel of this size in the viewport, preferring\n * below the anchor and lined up with its left edge.\n */\nfunction resolveAuto(\n view: Window,\n rect: DOMRect,\n panelWidth: number,\n panelHeight: number,\n gap: number\n): AnchoredCorner {\n const fitsBelow = rect.bottom + panelHeight + gap <= view.innerHeight;\n const fitsRight = rect.left + panelWidth <= view.innerWidth;\n if (fitsBelow) return fitsRight ? 'bottom-left' : 'bottom-right';\n return fitsRight ? 'top-left' : 'top-right';\n}\n\nconst samePosition = (a: AnchoredPosition, b: AnchoredPosition): boolean =>\n a.position === b.position &&\n a.top === b.top &&\n a.left === b.left &&\n a.minWidth === b.minWidth;\n\n/**\n * Places a floating panel against its anchor: resolves `auto` to a corner\n * and, for a panel fixed to the viewport, works out its coordinates. It\n * measures again on resize and on any scroll of the anchor's window (an\n * iframe's, when the anchor renders into one), so a fixed panel follows its\n * anchor, and with `followContent` after each render too. A measurement that\n * changes nothing doesn't render again.\n *\n * Measuring happens in a layout effect, so the panel is placed before it\n * paints. It needs both elements on the page while `active` is on, and\n * keeps the last placement when either is missing.\n *\n * @function useAnchoredPosition\n * @param anchorRef - The element the panel opens from.\n * @param panelRef - The floating panel.\n * @param options - Whether to measure, the corner asked for, and how the panel is placed.\n * @returns The corner the panel opens from, with coordinates when it is fixed.\n */\nexport function useAnchoredPosition(\n anchorRef: RefObject<HTMLElement | null>,\n panelRef: RefObject<HTMLElement | null>,\n {\n active,\n position,\n fixed,\n offset = 4,\n styledGap,\n matchWidth = false,\n followContent = false,\n }: UseAnchoredPositionOptions\n): AnchoredPosition {\n const [resolved, setResolved] = useState<AnchoredPosition>({\n position:\n position === undefined || position === 'auto' ? 'bottom-left' : position,\n });\n // The measurement while the panel is active, for `followContent` to run\n // again after a render.\n const updateRef = useRef<(() => void) | null>(null);\n\n useClientLayoutEffect(() => {\n if (!active) return undefined;\n const view =\n (anchorRef.current ?? panelRef.current)?.ownerDocument.defaultView ??\n window;\n const update = () => {\n const anchor = anchorRef.current;\n const panel = panelRef.current;\n if (!anchor || !panel) return;\n const rect = anchor.getBoundingClientRect();\n const measured = panel.getBoundingClientRect();\n // The width the panel has once it's at least as wide as the anchor.\n const width = matchWidth\n ? Math.max(measured.width, rect.width)\n : measured.width;\n const { height } = measured;\n const corner =\n position === 'auto'\n ? resolveAuto(\n view,\n rect,\n width,\n height,\n offset + (styledGap?.(panel) ?? 0)\n )\n : (position ?? 'bottom-left');\n // The default lines up with the anchor's inline start, so right to\n // left a fixed panel lines up the right edges. A named corner doesn't,\n // and a panel in place takes the default's side from its stylesheet.\n const startsRight =\n position === undefined &&\n fixed &&\n getComputedStyle(anchor).direction === 'rtl';\n const next: AnchoredPosition = fixed\n ? {\n position: corner,\n top: corner.startsWith('bottom')\n ? rect.bottom + offset\n : rect.top - height - offset,\n left:\n corner.endsWith('left') && !startsRight\n ? rect.left\n : rect.right - width,\n ...(matchWidth ? { minWidth: rect.width } : {}),\n }\n : { position: corner };\n setResolved(prev => (samePosition(prev, next) ? prev : next));\n };\n updateRef.current = update;\n update();\n view.addEventListener('resize', update, { passive: true });\n view.addEventListener('scroll', update, { passive: true, capture: true });\n return () => {\n updateRef.current = null;\n view.removeEventListener('resize', update);\n view.removeEventListener('scroll', update, { capture: true });\n };\n }, [\n active,\n anchorRef,\n panelRef,\n position,\n fixed,\n offset,\n styledGap,\n matchWidth,\n ]);\n\n // After every render, on purpose: the panel's content is what changed.\n useClientLayoutEffect(() => {\n if (followContent) updateRef.current?.();\n });\n\n return resolved;\n}\n"],"names":[],"mappings":";;;;;AAAA;AAgFA;;;;AAIG;AACG,SAAU,SAAS,CAAC,KAAkB,EAAA;IAC1C,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,GAAG,gBAAgB,CAAC,KAAK,CAAC;AAC3D,IAAA,OAAO,IAAI,CAAC,GAAG,CACb,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,EACpC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,CACxC;AACH;AAEA;;;AAGG;AACH,SAAS,WAAW,CAClB,IAAY,EACZ,IAAa,EACb,UAAkB,EAClB,WAAmB,EACnB,GAAW,EAAA;AAEX,IAAA,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,GAAG,WAAW,GAAG,GAAG,IAAI,IAAI,CAAC,WAAW;IACrE,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,GAAG,UAAU,IAAI,IAAI,CAAC,UAAU;AAC3D,IAAA,IAAI,SAAS;QAAE,OAAO,SAAS,GAAG,aAAa,GAAG,cAAc;IAChE,OAAO,SAAS,GAAG,UAAU,GAAG,WAAW;AAC7C;AAEA,MAAM,YAAY,GAAG,CAAC,CAAmB,EAAE,CAAmB,KAC5D,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,QAAQ;AACzB,IAAA,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG;AACf,IAAA,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI;AACjB,IAAA,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,QAAQ;AAE3B;;;;;;;;;;;;;;;;;AAiBG;AACG,SAAU,mBAAmB,CACjC,SAAwC,EACxC,QAAuC,EACvC,EACE,MAAM,EACN,QAAQ,EACR,KAAK,EACL,MAAM,GAAG,CAAC,EACV,SAAS,EACT,UAAU,GAAG,KAAK,EAClB,aAAa,GAAG,KAAK,GACM,EAAA;AAE7B,IAAA,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAmB;AACzD,QAAA,QAAQ,EACN,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,MAAM,GAAG,aAAa,GAAG,QAAQ;AAC3E,KAAA,CAAC;;;AAGF,IAAA,MAAM,SAAS,GAAG,MAAM,CAAsB,IAAI,CAAC;IAEnD,qBAAqB,CAAC,MAAK;AACzB,QAAA,IAAI,CAAC,MAAM;AAAE,YAAA,OAAO,SAAS;AAC7B,QAAA,MAAM,IAAI,GACR,CAAC,SAAS,CAAC,OAAO,IAAI,QAAQ,CAAC,OAAO,GAAG,aAAa,CAAC,WAAW;AAClE,YAAA,MAAM;QACR,MAAM,MAAM,GAAG,MAAK;AAClB,YAAA,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO;AAChC,YAAA,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO;AAC9B,YAAA,IAAI,CAAC,MAAM,IAAI,CAAC,KAAK;gBAAE;AACvB,YAAA,MAAM,IAAI,GAAG,MAAM,CAAC,qBAAqB,EAAE;AAC3C,YAAA,MAAM,QAAQ,GAAG,KAAK,CAAC,qBAAqB,EAAE;;YAE9C,MAAM,KAAK,GAAG;AACZ,kBAAE,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK;AACrC,kBAAE,QAAQ,CAAC,KAAK;AAClB,YAAA,MAAM,EAAE,MAAM,EAAE,GAAG,QAAQ;AAC3B,YAAA,MAAM,MAAM,GACV,QAAQ,KAAK;kBACT,WAAW,CACT,IAAI,EACJ,IAAI,EACJ,KAAK,EACL,MAAM,EACN,MAAM,IAAI,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;AAEtC,mBAAG,QAAQ,IAAI,aAAa,CAAC;;;;AAIjC,YAAA,MAAM,WAAW,GACf,QAAQ,KAAK,SAAS;gBACtB,KAAK;AACL,gBAAA,gBAAgB,CAAC,MAAM,CAAC,CAAC,SAAS,KAAK,KAAK;YAC9C,MAAM,IAAI,GAAqB;AAC7B,kBAAE;AACE,oBAAA,QAAQ,EAAE,MAAM;AAChB,oBAAA,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC,QAAQ;AAC7B,0BAAE,IAAI,CAAC,MAAM,GAAG;AAChB,0BAAE,IAAI,CAAC,GAAG,GAAG,MAAM,GAAG,MAAM;oBAC9B,IAAI,EACF,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC;0BACxB,IAAI,CAAC;AACP,0BAAE,IAAI,CAAC,KAAK,GAAG,KAAK;AACxB,oBAAA,IAAI,UAAU,GAAG,EAAE,QAAQ,EAAE,IAAI,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC;AAChD;AACH,kBAAE,EAAE,QAAQ,EAAE,MAAM,EAAE;YACxB,WAAW,CAAC,IAAI,KAAK,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC;AAC/D,QAAA,CAAC;AACD,QAAA,SAAS,CAAC,OAAO,GAAG,MAAM;AAC1B,QAAA,MAAM,EAAE;AACR,QAAA,IAAI,CAAC,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAC1D,QAAA,IAAI,CAAC,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AACzE,QAAA,OAAO,MAAK;AACV,YAAA,SAAS,CAAC,OAAO,GAAG,IAAI;AACxB,YAAA,IAAI,CAAC,mBAAmB,CAAC,QAAQ,EAAE,MAAM,CAAC;AAC1C,YAAA,IAAI,CAAC,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAC/D,QAAA,CAAC;AACH,IAAA,CAAC,EAAE;QACD,MAAM;QACN,SAAS;QACT,QAAQ;QACR,QAAQ;QACR,KAAK;QACL,MAAM;QACN,SAAS;QACT,UAAU;AACX,KAAA,CAAC;;IAGF,qBAAqB,CAAC,MAAK;AACzB,QAAA,IAAI,aAAa;AAAE,YAAA,SAAS,CAAC,OAAO,IAAI;AAC1C,IAAA,CAAC,CAAC;AAEF,IAAA,OAAO,QAAQ;AACjB;;"}
1
+ {"version":3,"file":"useAnchoredPosition.js","sources":["../../../src/helpers/useAnchoredPosition.ts"],"sourcesContent":["// INTERNAL: deliberately not exported from src/index.ts.\nimport { useRef, useState } from 'react';\nimport type { RefObject } from 'react';\nimport type { PickerPosition } from '../form/_pickerInternals/pickerTypes';\nimport { useClientLayoutEffect } from './useClientLayoutEffect';\n\n/** A corner of the anchor the panel opens from, once `auto` is resolved. */\nexport type AnchoredCorner = Exclude<PickerPosition, 'auto'>;\n\n/**\n * Where the panel goes: the corner it opens from and, when it is fixed to\n * the viewport, its coordinates there.\n */\nexport interface AnchoredPosition {\n position: AnchoredCorner;\n top?: number;\n left?: number;\n /**\n * With `matchWidth`, the anchor's width, which a fixed panel takes as its\n * `min-width`.\n */\n minWidth?: number;\n}\n\n/**\n * Options for `useAnchoredPosition`.\n */\nexport interface UseAnchoredPositionOptions {\n /** Whether the panel is on the page. Nothing is measured while it is not. */\n active: boolean;\n /**\n * The corner asked for, or `auto` to pick one that keeps the panel in the\n * viewport. A named corner is physical, whatever the page's direction.\n * Left out, the corner is `bottom-left` lined up with the anchor's inline\n * start, which is its right edge right to left. A panel in place gets that\n * from its stylesheet, as Popover's and the pickers' do; a fixed panel's\n * coordinates read the anchor's direction.\n */\n position?: PickerPosition;\n /**\n * Whether the panel is fixed to the viewport (it was portaled away from the\n * anchor), which needs coordinates. Otherwise the panel's CSS places it\n * against the anchor from the corner alone.\n */\n fixed: boolean;\n /**\n * The gap between the anchor and the panel, in pixels, that the hook puts\n * there itself: added to the fixed coordinates and to the room `auto` asks\n * for below the anchor. Popover and the pickers' popover pass `0` and take\n * their gap from a margin in their stylesheet, read through `styledGap`, so\n * a theme's offset moves the panel and `auto` alike. A new panel should do\n * the same rather than rely on this default, which no stylesheet sees.\n * @defaultValue 4\n */\n offset?: number;\n /**\n * Reads the gap the panel's own stylesheet puts between it and the anchor,\n * in pixels, each time the panel is measured. `auto` leaves room for it as\n * well; the coordinates don't include it, because the stylesheet applies it.\n */\n styledGap?: (panel: HTMLElement) => number;\n /**\n * Whether the panel is at least as wide as the anchor, as a list under its\n * field is. A panel in place gets that from its stylesheet. A fixed one\n * can't, so its placement carries the anchor's width as `minWidth` for the\n * panel to set, and its coordinates and `auto` already allow for it.\n * @defaultValue false\n */\n matchWidth?: boolean;\n /**\n * Measures again after each render of the component holding the hook,\n * before the panel paints, for a panel whose content that component\n * changes while it's open, as a filtered list's does. A change in size is\n * followed without it too, but a frame later, so a panel above its anchor\n * would show for a frame where its old height put it.\n * @defaultValue false\n */\n followContent?: boolean;\n}\n\n/**\n * A `styledGap` for a panel whose stylesheet puts the gap in a margin on the\n * side facing the anchor, negative on a portaled panel above it, so the\n * larger magnitude is the gap. In pixels.\n */\nexport function marginGap(panel: HTMLElement): number {\n const { marginTop, marginBottom } = getComputedStyle(panel);\n return Math.max(\n Math.abs(parseFloat(marginTop)) || 0,\n Math.abs(parseFloat(marginBottom)) || 0\n );\n}\n\n/**\n * The corner that keeps a panel of this size in the viewport, preferring\n * below the anchor and lined up with its left edge.\n */\nfunction resolveAuto(\n view: Window,\n rect: DOMRect,\n panelWidth: number,\n panelHeight: number,\n gap: number\n): AnchoredCorner {\n const fitsBelow = rect.bottom + panelHeight + gap <= view.innerHeight;\n const fitsRight = rect.left + panelWidth <= view.innerWidth;\n if (fitsBelow) return fitsRight ? 'bottom-left' : 'bottom-right';\n return fitsRight ? 'top-left' : 'top-right';\n}\n\nconst samePosition = (a: AnchoredPosition, b: AnchoredPosition): boolean =>\n a.position === b.position &&\n a.top === b.top &&\n a.left === b.left &&\n a.minWidth === b.minWidth;\n\n/**\n * Places a floating panel against its anchor: resolves `auto` to a corner\n * and, for a panel fixed to the viewport, works out its coordinates. It\n * measures again on resize, on any scroll of the anchor's window (an\n * iframe's, when the anchor renders into one), and when the panel or the\n * anchor changes size, so a fixed panel follows its anchor and its own\n * content. Those measure once in the next frame, however many arrive before\n * it. With `followContent` it also measures after each render. A\n * measurement that changes nothing doesn't render again.\n *\n * The first measurement happens in a layout effect, so the panel is placed\n * before it paints. It needs both elements on the page while `active` is\n * on, and keeps the last placement when either is missing.\n *\n * @function useAnchoredPosition\n * @param anchorRef - The element the panel opens from.\n * @param panelRef - The floating panel.\n * @param options - Whether to measure, the corner asked for, and how the panel is placed.\n * @returns The corner the panel opens from, with coordinates when it is fixed.\n */\nexport function useAnchoredPosition(\n anchorRef: RefObject<HTMLElement | null>,\n panelRef: RefObject<HTMLElement | null>,\n {\n active,\n position,\n fixed,\n offset = 4,\n styledGap,\n matchWidth = false,\n followContent = false,\n }: UseAnchoredPositionOptions\n): AnchoredPosition {\n const [resolved, setResolved] = useState<AnchoredPosition>({\n position:\n position === undefined || position === 'auto' ? 'bottom-left' : position,\n });\n // The measurement while the panel is active, for `followContent` to run\n // again after a render.\n const updateRef = useRef<(() => void) | null>(null);\n\n useClientLayoutEffect(() => {\n if (!active) return undefined;\n const view =\n (anchorRef.current ?? panelRef.current)?.ownerDocument.defaultView ??\n window;\n const update = () => {\n const anchor = anchorRef.current;\n const panel = panelRef.current;\n if (!anchor || !panel) return;\n const rect = anchor.getBoundingClientRect();\n const measured = panel.getBoundingClientRect();\n // The width the panel has once it's at least as wide as the anchor.\n const width = matchWidth\n ? Math.max(measured.width, rect.width)\n : measured.width;\n const { height } = measured;\n const corner =\n position === 'auto'\n ? resolveAuto(\n view,\n rect,\n width,\n height,\n offset + (styledGap?.(panel) ?? 0)\n )\n : (position ?? 'bottom-left');\n // The default lines up with the anchor's inline start, so right to\n // left a fixed panel lines up the right edges. A named corner doesn't,\n // and a panel in place takes the default's side from its stylesheet.\n const startsRight =\n position === undefined &&\n fixed &&\n getComputedStyle(anchor).direction === 'rtl';\n const next: AnchoredPosition = fixed\n ? {\n position: corner,\n top: corner.startsWith('bottom')\n ? rect.bottom + offset\n : rect.top - height - offset,\n left:\n corner.endsWith('left') && !startsRight\n ? rect.left\n : rect.right - width,\n ...(matchWidth ? { minWidth: rect.width } : {}),\n }\n : { position: corner };\n setResolved(prev => (samePosition(prev, next) ? prev : next));\n };\n updateRef.current = update;\n update();\n\n // A scroll, a resize or a change in size measures in the next frame,\n // once however many of them ask.\n let frame = 0;\n const schedule = () => {\n if (frame) return;\n frame = view.requestAnimationFrame(() => {\n frame = 0;\n update();\n });\n };\n view.addEventListener('resize', schedule, { passive: true });\n view.addEventListener('scroll', schedule, { passive: true, capture: true });\n // The panel's content can change size without the component holding the\n // hook rendering, as an image loading or a child's own state does, and\n // so can the anchor.\n const Observer = view.ResizeObserver;\n const resizes =\n typeof Observer === 'undefined' ? null : new Observer(schedule);\n for (const element of [anchorRef.current, panelRef.current]) {\n if (element) resizes?.observe(element);\n }\n return () => {\n updateRef.current = null;\n view.cancelAnimationFrame(frame);\n resizes?.disconnect();\n view.removeEventListener('resize', schedule);\n view.removeEventListener('scroll', schedule, { capture: true });\n };\n }, [\n active,\n anchorRef,\n panelRef,\n position,\n fixed,\n offset,\n styledGap,\n matchWidth,\n ]);\n\n // After every render, on purpose: the panel's content is what changed.\n useClientLayoutEffect(() => {\n if (followContent) updateRef.current?.();\n });\n\n return resolved;\n}\n"],"names":[],"mappings":"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"}
@@ -14,7 +14,7 @@ import { useBulmaClasses } from '../helpers/useBulmaClasses.js';
14
14
  * @returns {JSX.Element} The rendered level.
15
15
  * @see {@link https://bulma.io/documentation/layout/level/ | Bulma Level documentation}
16
16
  */
17
- const LevelComponent = ({ isMobile, className, children, color, bgColor, textColor, ...props }) => {
17
+ const LevelComponent = ({ as: Tag = 'nav', isMobile, className, children, color, bgColor, textColor, ...props }) => {
18
18
  const { bulmaHelperClasses, rest } = useBulmaClasses({
19
19
  color: textColor ?? color,
20
20
  backgroundColor: bgColor,
@@ -24,7 +24,7 @@ const LevelComponent = ({ isMobile, className, children, color, bgColor, textCol
24
24
  'is-mobile': isMobile,
25
25
  });
26
26
  const levelClasses = classNames(mainClass, bulmaHelperClasses, className);
27
- return (jsx("nav", { className: levelClasses, ...rest, children: children }));
27
+ return (jsx(Tag, { className: levelClasses, ...rest, children: children }));
28
28
  };
29
29
  /**
30
30
  * Left-aligned content.
@@ -1 +1 @@
1
- {"version":3,"file":"Level.js","sources":["../../../src/layout/Level.tsx"],"sourcesContent":["import React from 'react';\nimport { classNames, usePrefixedClassNames } from '../helpers/classNames';\nimport { withSubComponents } from '../helpers/withSubComponents';\nimport {\n type AnchorOnlyAttributes,\n ANCHOR_ONLY_ATTRS,\n omitAttrs,\n} from '../helpers/anchorAttrs';\nimport {\n useBulmaClasses,\n BulmaClassesProps,\n validColors,\n} from '../helpers/useBulmaClasses';\n\n/**\n * Props for the Level component.\n */\nexport interface LevelProps\n extends\n React.HTMLAttributes<HTMLElement>,\n Omit<BulmaClassesProps, 'color' | 'backgroundColor'> {\n /** Keeps the level horizontal on mobile (Bulma `is-mobile`). Without it\n * the level stacks vertically below tablet. */\n isMobile?: boolean;\n /** Bulma color modifier for the level. */\n color?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Bulma background color helper. */\n bgColor?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Bulma text color helper. */\n textColor?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Additional CSS classes. */\n className?: string;\n /** Level content (`Level.Left`, `Level.Right`, `Level.Item`). */\n children?: React.ReactNode;\n}\n\n/**\n * The `Level` component provides a flexible horizontal layout for your Bulma React UI, perfect for aligning items on the left and right, distributing items evenly, or centering statistics and controls.\n *\n * @function\n * @param {LevelProps} props - Props for the Level component.\n * @returns {JSX.Element} The rendered level.\n * @see {@link https://bulma.io/documentation/layout/level/ | Bulma Level documentation}\n */\nconst LevelComponent: React.FC<LevelProps> = ({\n isMobile,\n className,\n children,\n color,\n bgColor,\n textColor,\n ...props\n}) => {\n const { bulmaHelperClasses, rest } = useBulmaClasses({\n color: textColor ?? color,\n backgroundColor: bgColor,\n ...props,\n });\n const mainClass = usePrefixedClassNames('level', {\n 'is-mobile': isMobile,\n });\n const levelClasses = classNames(mainClass, bulmaHelperClasses, className);\n return (\n <nav className={levelClasses} {...rest}>\n {children}\n </nav>\n );\n};\n\n/**\n * Props for the LevelLeft component.\n */\nexport interface LevelLeftProps\n extends\n React.HTMLAttributes<HTMLDivElement>,\n Omit<BulmaClassesProps, 'color' | 'backgroundColor'> {\n /** Bulma color modifier. */\n color?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Background color. */\n bgColor?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Text color. */\n textColor?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Additional CSS classes. */\n className?: string;\n /** Content. */\n children?: React.ReactNode;\n}\n\n/**\n * Left-aligned content.\n *\n * @function\n * @param {LevelLeftProps} props - Props for the LevelLeft component.\n * @returns {JSX.Element} The rendered level left section.\n */\nexport const LevelLeft: React.FC<LevelLeftProps> = ({\n className,\n children,\n color,\n bgColor,\n textColor,\n ...props\n}) => {\n const { bulmaHelperClasses, rest } = useBulmaClasses({\n color: textColor ?? color,\n backgroundColor: bgColor,\n ...props,\n });\n const mainClass = usePrefixedClassNames('level-left');\n const levelLeftClasses = classNames(mainClass, bulmaHelperClasses, className);\n return (\n <div className={levelLeftClasses} {...rest}>\n {children}\n </div>\n );\n};\n\n/**\n * Props for the LevelRight component.\n */\nexport interface LevelRightProps\n extends\n React.HTMLAttributes<HTMLDivElement>,\n Omit<BulmaClassesProps, 'color' | 'backgroundColor'> {\n /** Bulma color modifier. */\n color?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Background color. */\n bgColor?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Text color. */\n textColor?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Additional CSS classes. */\n className?: string;\n /** Content. */\n children?: React.ReactNode;\n}\n\n/**\n * Right-aligned content.\n *\n * @function\n * @param {LevelRightProps} props - Props for the LevelRight component.\n * @returns {JSX.Element} The rendered level right section.\n */\nexport const LevelRight: React.FC<LevelRightProps> = ({\n className,\n children,\n color,\n bgColor,\n textColor,\n ...props\n}) => {\n const { bulmaHelperClasses, rest } = useBulmaClasses({\n color: textColor ?? color,\n backgroundColor: bgColor,\n ...props,\n });\n const mainClass = usePrefixedClassNames('level-right');\n const levelRightClasses = classNames(\n mainClass,\n bulmaHelperClasses,\n className\n );\n return (\n <div className={levelRightClasses} {...rest}>\n {children}\n </div>\n );\n};\n\n/**\n * The derived set plus `rel`.\n *\n * `rel` is not an anchor-only attribute — React declares it on every element, so\n * `AnchorOnlyAttributes` excludes it — but this component has always withheld it\n * from a non-anchor, so it is named separately rather than folded into the shared\n * set. That separation is what says which names come from where.\n *\n * The annotation is load-bearing: without it a typo adds a key nobody strips, and\n * widening the key type to `string` also erases `omitAttrs`'s return type.\n */\nconst STRIP_FROM_NON_ANCHOR: Readonly<\n Record<keyof AnchorOnlyAttributes | 'rel', true>\n> = { ...ANCHOR_ONLY_ATTRS, rel: true };\n\n/**\n * Props for the LevelItem component.\n *\n * The anchor attributes arrive through `AnchorOnlyAttributes`, at every `as`, and\n * are forwarded only when the tag is an `<a>` — so `<Level.Item as=\"p\" download>` compiles and\n * renders a `<p>` without it. That asymmetry is deliberate for now: deriving\n * them from `as` instead is what makes the dead pair a type error, and it also\n * stops `const p: LevelItemProps = { href }` compiling for consumers who write\n * it today. #672 carries that half, labelled `next-major`.\n *\n * What that set must NOT become is a hand-written list. Enumerating only `href`,\n * `target` and `rel` made every other anchor attribute a type error even at\n * `as=\"a\"`, which is what #641 reported; `helpers/anchorAttrs.ts` derives it from\n * React instead, and `ANCHOR_ONLY_ATTRS` there is the guard to protect.\n */\nexport interface LevelItemProps\n extends\n AnchorOnlyAttributes,\n React.HTMLAttributes<\n HTMLDivElement | HTMLParagraphElement | HTMLAnchorElement\n >,\n Omit<BulmaClassesProps, 'color' | 'backgroundColor'> {\n /** Element type to render. */\n as?: 'div' | 'p' | 'a';\n /** Center the text in the item. */\n hasTextCentered?: boolean;\n /** Bulma color modifier. */\n color?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Background color. */\n bgColor?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Text color. */\n textColor?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Additional CSS classes. */\n className?: string;\n /** Content. */\n children?: React.ReactNode;\n}\n\n/**\n * Individual item, can be rendered as `div`, `p`, or `a`.\n *\n * @function\n * @param {LevelItemProps} props - Props for the LevelItem component.\n * @returns {JSX.Element} The rendered level item.\n */\nexport const LevelItem: React.FC<LevelItemProps> = ({\n as = 'div',\n hasTextCentered,\n className,\n children,\n color,\n bgColor,\n textColor,\n ...props\n}) => {\n const { bulmaHelperClasses, rest } = useBulmaClasses({\n color: textColor ?? color,\n backgroundColor: bgColor,\n ...props,\n });\n const Tag = as;\n\n const mainClass = usePrefixedClassNames('level-item', {\n 'has-text-centered': hasTextCentered,\n });\n const levelItemClasses = classNames(mainClass, bulmaHelperClasses, className);\n\n // The anchor's own attributes reach an `<a>` and nothing else. The type\n // declares them at every `as` — narrowing that is source-breaking (#672) — so\n // the runtime is what keeps `<Level.Item as=\"p\" download>` from rendering a\n // dead attribute.\n // `STRIP_FROM_NON_ANCHOR` above names the set and why `rel` is in it.\n\n if (Tag === 'a') {\n return (\n <a className={levelItemClasses} {...rest}>\n {children}\n </a>\n );\n }\n\n const withoutAnchorAttrs = omitAttrs(rest, STRIP_FROM_NON_ANCHOR);\n\n return (\n <Tag className={levelItemClasses} {...withoutAnchorAttrs}>\n {children}\n </Tag>\n );\n};\n\nexport const Level = withSubComponents(\n LevelComponent,\n {\n Left: LevelLeft,\n Right: LevelRight,\n Item: LevelItem,\n },\n 'Level'\n);\n\nexport default Level;\n"],"names":["_jsx"],"mappings":"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"}
1
+ {"version":3,"file":"Level.js","sources":["../../../src/layout/Level.tsx"],"sourcesContent":["import React from 'react';\nimport { classNames, usePrefixedClassNames } from '../helpers/classNames';\nimport { withSubComponents } from '../helpers/withSubComponents';\nimport {\n type AnchorOnlyAttributes,\n ANCHOR_ONLY_ATTRS,\n omitAttrs,\n} from '../helpers/anchorAttrs';\nimport {\n useBulmaClasses,\n BulmaClassesProps,\n validColors,\n} from '../helpers/useBulmaClasses';\n\n/**\n * Props for the Level component.\n */\nexport interface LevelProps\n extends\n React.HTMLAttributes<HTMLElement>,\n Omit<BulmaClassesProps, 'color' | 'backgroundColor'> {\n /**\n * HTML element to render (default: `nav`, as in Bulma's markup). A `nav` is\n * a `navigation` landmark, so keep it for a row of links. A row that is not\n * navigation, such as figures or a toolbar, takes `div`, which is no\n * landmark. `header` suits a level that opens a section and `footer` one\n * that closes it. A `header` is a `banner` landmark, and a `footer` a\n * `contentinfo` one, only when no `section`, `article`, `aside`, `nav` or\n * `main` is around it.\n */\n as?: 'nav' | 'div' | 'header' | 'footer';\n /** Keeps the level horizontal on mobile (Bulma `is-mobile`). Without it\n * the level stacks vertically below tablet. */\n isMobile?: boolean;\n /** Bulma color modifier for the level. */\n color?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Bulma background color helper. */\n bgColor?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Bulma text color helper. */\n textColor?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Additional CSS classes. */\n className?: string;\n /** Level content (`Level.Left`, `Level.Right`, `Level.Item`). */\n children?: React.ReactNode;\n}\n\n/**\n * The `Level` component provides a flexible horizontal layout for your Bulma React UI, perfect for aligning items on the left and right, distributing items evenly, or centering statistics and controls.\n *\n * @function\n * @param {LevelProps} props - Props for the Level component.\n * @returns {JSX.Element} The rendered level.\n * @see {@link https://bulma.io/documentation/layout/level/ | Bulma Level documentation}\n */\nconst LevelComponent: React.FC<LevelProps> = ({\n as: Tag = 'nav',\n isMobile,\n className,\n children,\n color,\n bgColor,\n textColor,\n ...props\n}) => {\n const { bulmaHelperClasses, rest } = useBulmaClasses({\n color: textColor ?? color,\n backgroundColor: bgColor,\n ...props,\n });\n const mainClass = usePrefixedClassNames('level', {\n 'is-mobile': isMobile,\n });\n const levelClasses = classNames(mainClass, bulmaHelperClasses, className);\n return (\n <Tag className={levelClasses} {...rest}>\n {children}\n </Tag>\n );\n};\n\n/**\n * Props for the LevelLeft component.\n */\nexport interface LevelLeftProps\n extends\n React.HTMLAttributes<HTMLDivElement>,\n Omit<BulmaClassesProps, 'color' | 'backgroundColor'> {\n /** Bulma color modifier. */\n color?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Background color. */\n bgColor?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Text color. */\n textColor?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Additional CSS classes. */\n className?: string;\n /** Content. */\n children?: React.ReactNode;\n}\n\n/**\n * Left-aligned content.\n *\n * @function\n * @param {LevelLeftProps} props - Props for the LevelLeft component.\n * @returns {JSX.Element} The rendered level left section.\n */\nexport const LevelLeft: React.FC<LevelLeftProps> = ({\n className,\n children,\n color,\n bgColor,\n textColor,\n ...props\n}) => {\n const { bulmaHelperClasses, rest } = useBulmaClasses({\n color: textColor ?? color,\n backgroundColor: bgColor,\n ...props,\n });\n const mainClass = usePrefixedClassNames('level-left');\n const levelLeftClasses = classNames(mainClass, bulmaHelperClasses, className);\n return (\n <div className={levelLeftClasses} {...rest}>\n {children}\n </div>\n );\n};\n\n/**\n * Props for the LevelRight component.\n */\nexport interface LevelRightProps\n extends\n React.HTMLAttributes<HTMLDivElement>,\n Omit<BulmaClassesProps, 'color' | 'backgroundColor'> {\n /** Bulma color modifier. */\n color?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Background color. */\n bgColor?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Text color. */\n textColor?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Additional CSS classes. */\n className?: string;\n /** Content. */\n children?: React.ReactNode;\n}\n\n/**\n * Right-aligned content.\n *\n * @function\n * @param {LevelRightProps} props - Props for the LevelRight component.\n * @returns {JSX.Element} The rendered level right section.\n */\nexport const LevelRight: React.FC<LevelRightProps> = ({\n className,\n children,\n color,\n bgColor,\n textColor,\n ...props\n}) => {\n const { bulmaHelperClasses, rest } = useBulmaClasses({\n color: textColor ?? color,\n backgroundColor: bgColor,\n ...props,\n });\n const mainClass = usePrefixedClassNames('level-right');\n const levelRightClasses = classNames(\n mainClass,\n bulmaHelperClasses,\n className\n );\n return (\n <div className={levelRightClasses} {...rest}>\n {children}\n </div>\n );\n};\n\n/**\n * The derived set plus `rel`.\n *\n * `rel` is not an anchor-only attribute — React declares it on every element, so\n * `AnchorOnlyAttributes` excludes it — but this component has always withheld it\n * from a non-anchor, so it is named separately rather than folded into the shared\n * set. That separation is what says which names come from where.\n *\n * The annotation is load-bearing: without it a typo adds a key nobody strips, and\n * widening the key type to `string` also erases `omitAttrs`'s return type.\n */\nconst STRIP_FROM_NON_ANCHOR: Readonly<\n Record<keyof AnchorOnlyAttributes | 'rel', true>\n> = { ...ANCHOR_ONLY_ATTRS, rel: true };\n\n/**\n * Props for the LevelItem component.\n *\n * The anchor attributes arrive through `AnchorOnlyAttributes`, at every `as`, and\n * are forwarded only when the tag is an `<a>` — so `<Level.Item as=\"p\" download>` compiles and\n * renders a `<p>` without it. That asymmetry is deliberate for now: deriving\n * them from `as` instead is what makes the dead pair a type error, and it also\n * stops `const p: LevelItemProps = { href }` compiling for consumers who write\n * it today. #672 carries that half, labelled `next-major`.\n *\n * What that set must NOT become is a hand-written list. Enumerating only `href`,\n * `target` and `rel` made every other anchor attribute a type error even at\n * `as=\"a\"`, which is what #641 reported; `helpers/anchorAttrs.ts` derives it from\n * React instead, and `ANCHOR_ONLY_ATTRS` there is the guard to protect.\n */\nexport interface LevelItemProps\n extends\n AnchorOnlyAttributes,\n React.HTMLAttributes<\n HTMLDivElement | HTMLParagraphElement | HTMLAnchorElement\n >,\n Omit<BulmaClassesProps, 'color' | 'backgroundColor'> {\n /** Element type to render. */\n as?: 'div' | 'p' | 'a';\n /** Center the text in the item. */\n hasTextCentered?: boolean;\n /** Bulma color modifier. */\n color?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Background color. */\n bgColor?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Text color. */\n textColor?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Additional CSS classes. */\n className?: string;\n /** Content. */\n children?: React.ReactNode;\n}\n\n/**\n * Individual item, can be rendered as `div`, `p`, or `a`.\n *\n * @function\n * @param {LevelItemProps} props - Props for the LevelItem component.\n * @returns {JSX.Element} The rendered level item.\n */\nexport const LevelItem: React.FC<LevelItemProps> = ({\n as = 'div',\n hasTextCentered,\n className,\n children,\n color,\n bgColor,\n textColor,\n ...props\n}) => {\n const { bulmaHelperClasses, rest } = useBulmaClasses({\n color: textColor ?? color,\n backgroundColor: bgColor,\n ...props,\n });\n const Tag = as;\n\n const mainClass = usePrefixedClassNames('level-item', {\n 'has-text-centered': hasTextCentered,\n });\n const levelItemClasses = classNames(mainClass, bulmaHelperClasses, className);\n\n // The anchor's own attributes reach an `<a>` and nothing else. The type\n // declares them at every `as` — narrowing that is source-breaking (#672) — so\n // the runtime is what keeps `<Level.Item as=\"p\" download>` from rendering a\n // dead attribute.\n // `STRIP_FROM_NON_ANCHOR` above names the set and why `rel` is in it.\n\n if (Tag === 'a') {\n return (\n <a className={levelItemClasses} {...rest}>\n {children}\n </a>\n );\n }\n\n const withoutAnchorAttrs = omitAttrs(rest, STRIP_FROM_NON_ANCHOR);\n\n return (\n <Tag className={levelItemClasses} {...withoutAnchorAttrs}>\n {children}\n </Tag>\n );\n};\n\nexport const Level = withSubComponents(\n LevelComponent,\n {\n Left: LevelLeft,\n Right: LevelRight,\n Item: LevelItem,\n },\n 'Level'\n);\n\nexport default Level;\n"],"names":["_jsx"],"mappings":"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"}