@mieweb/ui 0.7.1-dev.15 → 0.7.1-dev.16

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/{chunk-XCVBCY7L.cjs → chunk-26DPQUSB.cjs} +4 -4
  2. package/dist/{chunk-XCVBCY7L.cjs.map → chunk-26DPQUSB.cjs.map} +1 -1
  3. package/dist/{chunk-BZMBCKW2.cjs → chunk-3G2HFPCC.cjs} +8 -8
  4. package/dist/{chunk-BZMBCKW2.cjs.map → chunk-3G2HFPCC.cjs.map} +1 -1
  5. package/dist/{chunk-UXBRRSJ6.js → chunk-5BDCQBYW.js} +3 -3
  6. package/dist/{chunk-UXBRRSJ6.js.map → chunk-5BDCQBYW.js.map} +1 -1
  7. package/dist/{chunk-C7I3ZGMQ.cjs → chunk-6J7UGYT5.cjs} +4 -4
  8. package/dist/{chunk-C7I3ZGMQ.cjs.map → chunk-6J7UGYT5.cjs.map} +1 -1
  9. package/dist/{chunk-JJNCQMR5.js → chunk-BMRQ4VME.js} +3 -3
  10. package/dist/{chunk-JJNCQMR5.js.map → chunk-BMRQ4VME.js.map} +1 -1
  11. package/dist/{chunk-QA6ZDHFP.js → chunk-BOOJDRJO.js} +35 -11
  12. package/dist/chunk-BOOJDRJO.js.map +1 -0
  13. package/dist/{chunk-34LGPMO4.js → chunk-DLBV42JD.js} +3 -3
  14. package/dist/{chunk-34LGPMO4.js.map → chunk-DLBV42JD.js.map} +1 -1
  15. package/dist/{chunk-IXWRD4AP.js → chunk-EKRT7K2K.js} +3 -3
  16. package/dist/{chunk-IXWRD4AP.js.map → chunk-EKRT7K2K.js.map} +1 -1
  17. package/dist/{chunk-MHD5HZ4X.js → chunk-FDV7EQWH.js} +3 -3
  18. package/dist/{chunk-MHD5HZ4X.js.map → chunk-FDV7EQWH.js.map} +1 -1
  19. package/dist/{chunk-EDBGSGUK.cjs → chunk-GLRLOJMV.cjs} +4 -4
  20. package/dist/{chunk-EDBGSGUK.cjs.map → chunk-GLRLOJMV.cjs.map} +1 -1
  21. package/dist/{chunk-GDBPFHNX.js → chunk-HIDV32ZX.js} +3 -3
  22. package/dist/{chunk-GDBPFHNX.js.map → chunk-HIDV32ZX.js.map} +1 -1
  23. package/dist/{chunk-ZDEYV373.cjs → chunk-MYFZYUPR.cjs} +35 -11
  24. package/dist/chunk-MYFZYUPR.cjs.map +1 -0
  25. package/dist/{chunk-I2BKK3AQ.js → chunk-NGLI2MSM.js} +3 -3
  26. package/dist/{chunk-I2BKK3AQ.js.map → chunk-NGLI2MSM.js.map} +1 -1
  27. package/dist/{chunk-IS5PNYR7.js → chunk-P6L74SKG.js} +3 -3
  28. package/dist/{chunk-IS5PNYR7.js.map → chunk-P6L74SKG.js.map} +1 -1
  29. package/dist/{chunk-GKWWFJDB.cjs → chunk-Q5VBO3I5.cjs} +5 -5
  30. package/dist/{chunk-GKWWFJDB.cjs.map → chunk-Q5VBO3I5.cjs.map} +1 -1
  31. package/dist/{chunk-UTCFBBOD.cjs → chunk-QI2SB6U3.cjs} +7 -7
  32. package/dist/{chunk-UTCFBBOD.cjs.map → chunk-QI2SB6U3.cjs.map} +1 -1
  33. package/dist/{chunk-477Z2DYN.js → chunk-QOBNYNKZ.js} +4 -4
  34. package/dist/{chunk-477Z2DYN.js.map → chunk-QOBNYNKZ.js.map} +1 -1
  35. package/dist/{chunk-U4HA2WHA.cjs → chunk-RBS3GHDZ.cjs} +4 -4
  36. package/dist/{chunk-U4HA2WHA.cjs.map → chunk-RBS3GHDZ.cjs.map} +1 -1
  37. package/dist/{chunk-4G3NJLQA.js → chunk-RGRSJYZF.js} +3 -3
  38. package/dist/{chunk-4G3NJLQA.js.map → chunk-RGRSJYZF.js.map} +1 -1
  39. package/dist/{chunk-YXHX2DAK.cjs → chunk-RYQ3S3KO.cjs} +5 -5
  40. package/dist/{chunk-YXHX2DAK.cjs.map → chunk-RYQ3S3KO.cjs.map} +1 -1
  41. package/dist/{chunk-C2NNNOSU.cjs → chunk-VVI32P7L.cjs} +4 -4
  42. package/dist/{chunk-C2NNNOSU.cjs.map → chunk-VVI32P7L.cjs.map} +1 -1
  43. package/dist/{chunk-OJEXXH5D.cjs → chunk-ZBI52NP2.cjs} +4 -4
  44. package/dist/{chunk-OJEXXH5D.cjs.map → chunk-ZBI52NP2.cjs.map} +1 -1
  45. package/dist/components/Autocomplete/index.cjs +3 -3
  46. package/dist/components/Autocomplete/index.js +2 -2
  47. package/dist/components/CountryCodeDropdown/index.cjs +5 -5
  48. package/dist/components/CountryCodeDropdown/index.js +2 -2
  49. package/dist/components/DateInput/index.cjs +3 -3
  50. package/dist/components/DateInput/index.js +2 -2
  51. package/dist/components/Dropdown/index.cjs +8 -8
  52. package/dist/components/Dropdown/index.d.cts +1 -1
  53. package/dist/components/Dropdown/index.d.ts +1 -1
  54. package/dist/components/Dropdown/index.js +2 -2
  55. package/dist/components/MediaEditor/index.cjs +8 -8
  56. package/dist/components/MediaEditor/index.js +3 -3
  57. package/dist/components/RichTextEditor/index.cjs +6 -6
  58. package/dist/components/RichTextEditor/index.js +3 -3
  59. package/dist/components/Select/index.cjs +4 -4
  60. package/dist/components/Select/index.js +2 -2
  61. package/dist/components/SuperChat/index.cjs +8 -8
  62. package/dist/components/SuperChat/index.js +3 -3
  63. package/dist/components/SuperChat/plugins/index.cjs +4 -4
  64. package/dist/components/SuperChat/plugins/index.js +3 -3
  65. package/dist/esheet.cjs +7 -7
  66. package/dist/esheet.js +4 -4
  67. package/dist/hooks/index.cjs +2 -2
  68. package/dist/hooks/index.d.cts +1 -1
  69. package/dist/hooks/index.d.ts +1 -1
  70. package/dist/hooks/index.js +1 -1
  71. package/dist/index.cjs +481 -157
  72. package/dist/index.cjs.map +1 -1
  73. package/dist/index.d.cts +37 -2
  74. package/dist/index.d.ts +37 -2
  75. package/dist/index.js +343 -20
  76. package/dist/index.js.map +1 -1
  77. package/dist/{useAnchoredPosition-nXdSFKHf.d.cts → useAnchoredPosition-C7PNglzD.d.cts} +6 -2
  78. package/dist/{useAnchoredPosition-nXdSFKHf.d.ts → useAnchoredPosition-C7PNglzD.d.ts} +6 -2
  79. package/package.json +1 -1
  80. package/dist/chunk-QA6ZDHFP.js.map +0 -1
  81. package/dist/chunk-ZDEYV373.cjs.map +0 -1
@@ -41,6 +41,8 @@ function useAnchoredPosition({
41
41
  matchWidth = false,
42
42
  matchMinWidth = false,
43
43
  viewportPadding = 8,
44
+ allowFlip = true,
45
+ boundaryRef,
44
46
  maxHeight
45
47
  }) {
46
48
  const anchorRef = React__namespace.useRef(null);
@@ -56,18 +58,37 @@ function useAnchoredPosition({
56
58
  const rect = anchor.getBoundingClientRect();
57
59
  const viewportWidth = window.innerWidth;
58
60
  const viewportHeight = window.innerHeight;
61
+ const boundaryRect = boundaryRef?.current?.getBoundingClientRect();
62
+ const bounds = boundaryRect ?? {
63
+ top: 0,
64
+ right: viewportWidth,
65
+ bottom: viewportHeight,
66
+ left: 0
67
+ };
68
+ const leftLimit = Math.max(bounds.left + viewportPadding, viewportPadding);
69
+ const rightLimit = Math.min(
70
+ bounds.right - viewportPadding,
71
+ viewportWidth - viewportPadding
72
+ );
73
+ const topLimit = Math.max(bounds.top + viewportPadding, viewportPadding);
74
+ const bottomLimit = Math.min(
75
+ bounds.bottom - viewportPadding,
76
+ viewportHeight - viewportPadding
77
+ );
59
78
  const contentHeight = Math.min(
60
79
  floating.scrollHeight,
61
80
  maxHeight ?? Infinity
62
81
  );
63
82
  const floatingWidth = matchWidth ? rect.width : Math.max(floating.offsetWidth, matchMinWidth ? rect.width : 0);
64
- const spaceBelow = viewportHeight - rect.bottom - offset - viewportPadding;
65
- const spaceAbove = rect.top - offset - viewportPadding;
83
+ const availableWidth = Math.max(rightLimit - leftLimit, 0);
84
+ const positionedWidth = Math.min(floatingWidth, availableWidth);
85
+ const spaceBelow = bottomLimit - rect.bottom - offset;
86
+ const spaceAbove = rect.top - topLimit - offset;
66
87
  const preferTop = placement.startsWith("top");
67
- let side;
68
- if (preferTop) {
88
+ let side = preferTop ? "top" : "bottom";
89
+ if (allowFlip && preferTop) {
69
90
  side = spaceAbove < contentHeight && spaceBelow > spaceAbove ? "bottom" : "top";
70
- } else {
91
+ } else if (allowFlip) {
71
92
  side = spaceBelow < contentHeight && spaceAbove > spaceBelow ? "top" : "bottom";
72
93
  }
73
94
  const availableHeight = Math.max(
@@ -75,10 +96,10 @@ function useAnchoredPosition({
75
96
  0
76
97
  );
77
98
  const align = placement.endsWith("-start") ? "left" : placement.endsWith("-end") ? "right" : "center";
78
- let left = align === "left" ? rect.left : align === "right" ? rect.right - floatingWidth : rect.left + rect.width / 2 - floatingWidth / 2;
99
+ let left = align === "left" ? rect.left : align === "right" ? rect.right - positionedWidth : rect.left + rect.width / 2 - positionedWidth / 2;
79
100
  left = Math.min(
80
- Math.max(left, viewportPadding),
81
- Math.max(viewportWidth - floatingWidth - viewportPadding, viewportPadding)
101
+ Math.max(left, leftLimit),
102
+ Math.max(rightLimit - positionedWidth, leftLimit)
82
103
  );
83
104
  setActualSide(side);
84
105
  setStyle({
@@ -87,6 +108,7 @@ function useAnchoredPosition({
87
108
  ...side === "top" ? { bottom: viewportHeight - rect.top + offset } : { top: rect.bottom + offset },
88
109
  ...matchWidth ? { width: rect.width } : {},
89
110
  ...matchMinWidth ? { minWidth: rect.width } : {},
111
+ maxWidth: availableWidth,
90
112
  maxHeight: Math.min(availableHeight, maxHeight ?? Infinity),
91
113
  zIndex: 9999,
92
114
  transition: "none"
@@ -97,7 +119,9 @@ function useAnchoredPosition({
97
119
  maxHeight,
98
120
  offset,
99
121
  placement,
100
- viewportPadding
122
+ viewportPadding,
123
+ allowFlip,
124
+ boundaryRef
101
125
  ]);
102
126
  React__namespace.useLayoutEffect(() => {
103
127
  if (open) {
@@ -135,5 +159,5 @@ function useAnchoredPosition({
135
159
  }
136
160
 
137
161
  exports.useAnchoredPosition = useAnchoredPosition;
138
- //# sourceMappingURL=chunk-ZDEYV373.cjs.map
139
- //# sourceMappingURL=chunk-ZDEYV373.cjs.map
162
+ //# sourceMappingURL=chunk-MYFZYUPR.cjs.map
163
+ //# sourceMappingURL=chunk-MYFZYUPR.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/hooks/useAnchoredPosition.ts"],"names":["React"],"mappings":"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","file":"chunk-MYFZYUPR.cjs","sourcesContent":["'use client';\n\nimport * as React from 'react';\n\nexport type AnchoredPlacement =\n | 'bottom-start'\n | 'bottom-end'\n | 'bottom'\n | 'top-start'\n | 'top-end'\n | 'top';\n\nexport interface UseAnchoredPositionOptions {\n /** Whether the floating element is currently shown */\n open: boolean;\n /** Preferred placement relative to the anchor (flips when out of space) */\n placement?: AnchoredPlacement;\n /** Gap between the anchor and the floating element, in px */\n offset?: number;\n /** Force the floating element to the anchor's width */\n matchWidth?: boolean;\n /** Use the anchor's width as the floating element's minimum width */\n matchMinWidth?: boolean;\n /** Minimum distance from the viewport edges, in px */\n viewportPadding?: number;\n /** Flip to the opposite vertical side when the preferred side is cramped */\n allowFlip?: boolean;\n /** Optional element whose visible rectangle also constrains the popup */\n boundaryRef?: React.RefObject<HTMLElement | null>;\n /**\n * Additional cap on the floating element's height, in px. The height is\n * always clamped to the available viewport space; this only lowers that\n * limit further (omitting it does not remove the viewport constraint).\n */\n maxHeight?: number;\n}\n\nexport interface UseAnchoredPositionReturn<\n TAnchor extends HTMLElement,\n TFloating extends HTMLElement,\n> {\n /** Attach to the element the popup is anchored to (trigger/input) */\n anchorRef: React.RefObject<TAnchor | null>;\n /** Attach to the floating element (menu/listbox/panel) */\n floatingRef: React.RefObject<TFloating | null>;\n /** Fixed-position style for the floating element — spread onto it */\n style: React.CSSProperties;\n /** Vertical side in use after flipping ('top' or 'bottom') */\n actualSide: 'top' | 'bottom';\n /** Recompute the position (e.g. after async content loads) */\n update: () => void;\n}\n\nconst HIDDEN_STYLE: React.CSSProperties = {\n position: 'fixed',\n top: 0,\n left: 0,\n visibility: 'hidden',\n zIndex: 9999,\n // Never let `transition-*` utilities animate top/left from the hidden\n // (0,0) mount position to the computed one (keyframe animations like\n // `animate-in` are unaffected).\n transition: 'none',\n};\n\n/**\n * Positions a floating element (dropdown menu, autocomplete listbox,\n * date-picker calendar, …) relative to an anchor using `position: fixed`,\n * so it is never clipped by `overflow: hidden` ancestors.\n *\n * Render the floating element through `createPortal(..., document.body)`\n * and spread the returned `style` onto it. The hook:\n * - flips vertically when there is not enough space on the preferred side\n * - clamps horizontally to the viewport or optional boundary element\n * - constrains `maxHeight` to the available space (add `overflow-auto`)\n * - tracks scroll, resize, and anchor/content size changes while open\n *\n * @example\n * ```tsx\n * const { anchorRef, floatingRef, style } = useAnchoredPosition<\n * HTMLButtonElement,\n * HTMLDivElement\n * >({ open, placement: 'bottom-start' });\n *\n * <button ref={anchorRef} onClick={() => setOpen(!open)}>Open</button>\n * {open &&\n * createPortal(\n * <div ref={floatingRef} style={style} className=\"overflow-auto …\">…</div>,\n * document.body\n * )}\n * ```\n */\nexport function useAnchoredPosition<\n TAnchor extends HTMLElement = HTMLElement,\n TFloating extends HTMLElement = HTMLElement,\n>({\n open,\n placement = 'bottom-start',\n offset = 4,\n matchWidth = false,\n matchMinWidth = false,\n viewportPadding = 8,\n allowFlip = true,\n boundaryRef,\n maxHeight,\n}: UseAnchoredPositionOptions): UseAnchoredPositionReturn<TAnchor, TFloating> {\n const anchorRef = React.useRef<TAnchor | null>(null);\n const floatingRef = React.useRef<TFloating | null>(null);\n const [style, setStyle] = React.useState<React.CSSProperties>(HIDDEN_STYLE);\n const [actualSide, setActualSide] = React.useState<'top' | 'bottom'>(\n placement.startsWith('top') ? 'top' : 'bottom'\n );\n\n const update = React.useCallback(() => {\n const anchor = anchorRef.current;\n const floating = floatingRef.current;\n if (!anchor || !floating) return;\n\n const rect = anchor.getBoundingClientRect();\n const viewportWidth = window.innerWidth;\n const viewportHeight = window.innerHeight;\n const boundaryRect = boundaryRef?.current?.getBoundingClientRect();\n const bounds = boundaryRect ?? {\n top: 0,\n right: viewportWidth,\n bottom: viewportHeight,\n left: 0,\n };\n const leftLimit = Math.max(bounds.left + viewportPadding, viewportPadding);\n const rightLimit = Math.min(\n bounds.right - viewportPadding,\n viewportWidth - viewportPadding\n );\n const topLimit = Math.max(bounds.top + viewportPadding, viewportPadding);\n const bottomLimit = Math.min(\n bounds.bottom - viewportPadding,\n viewportHeight - viewportPadding\n );\n\n // Natural content size (scrollHeight so a previously applied maxHeight\n // doesn't skew the flip decision).\n const contentHeight = Math.min(\n floating.scrollHeight,\n maxHeight ?? Infinity\n );\n // With matchMinWidth the rendered width is at least the anchor's width,\n // even if offsetWidth was measured before minWidth applied.\n const floatingWidth = matchWidth\n ? rect.width\n : Math.max(floating.offsetWidth, matchMinWidth ? rect.width : 0);\n const availableWidth = Math.max(rightLimit - leftLimit, 0);\n const positionedWidth = Math.min(floatingWidth, availableWidth);\n\n // --- Vertical: preferred side, flip when out of space -------------------\n const spaceBelow = bottomLimit - rect.bottom - offset;\n const spaceAbove = rect.top - topLimit - offset;\n const preferTop = placement.startsWith('top');\n let side: 'top' | 'bottom' = preferTop ? 'top' : 'bottom';\n if (allowFlip && preferTop) {\n side =\n spaceAbove < contentHeight && spaceBelow > spaceAbove\n ? 'bottom'\n : 'top';\n } else if (allowFlip) {\n side =\n spaceBelow < contentHeight && spaceAbove > spaceBelow\n ? 'top'\n : 'bottom';\n }\n const availableHeight = Math.max(\n side === 'top' ? spaceAbove : spaceBelow,\n 0\n );\n\n // --- Horizontal: -start aligns left edges, -end aligns right edges ------\n const align = placement.endsWith('-start')\n ? 'left'\n : placement.endsWith('-end')\n ? 'right'\n : 'center';\n let left =\n align === 'left'\n ? rect.left\n : align === 'right'\n ? rect.right - positionedWidth\n : rect.left + rect.width / 2 - positionedWidth / 2;\n left = Math.min(\n Math.max(left, leftLimit),\n Math.max(rightLimit - positionedWidth, leftLimit)\n );\n\n setActualSide(side);\n setStyle({\n position: 'fixed',\n left,\n ...(side === 'top'\n ? { bottom: viewportHeight - rect.top + offset }\n : { top: rect.bottom + offset }),\n ...(matchWidth ? { width: rect.width } : {}),\n ...(matchMinWidth ? { minWidth: rect.width } : {}),\n maxWidth: availableWidth,\n maxHeight: Math.min(availableHeight, maxHeight ?? Infinity),\n zIndex: 9999,\n transition: 'none',\n });\n }, [\n matchMinWidth,\n matchWidth,\n maxHeight,\n offset,\n placement,\n viewportPadding,\n allowFlip,\n boundaryRef,\n ]);\n\n // Position synchronously before paint when opening / re-rendering open.\n React.useLayoutEffect(() => {\n if (open) {\n update();\n } else {\n setStyle(HIDDEN_STYLE);\n }\n }, [open, update]);\n\n // Track scroll/resize and anchor/content size changes while open.\n React.useEffect(() => {\n if (!open) return;\n\n // Coalesce bursts (scroll/resize fire per event) into one layout\n // read + state update per frame.\n let frame = 0;\n const scheduleUpdate = () => {\n if (frame) return;\n frame = window.requestAnimationFrame(() => {\n frame = 0;\n update();\n });\n };\n\n window.addEventListener('scroll', scheduleUpdate, true);\n window.addEventListener('resize', scheduleUpdate);\n\n let resizeObserver: globalThis.ResizeObserver | undefined;\n if (typeof globalThis.ResizeObserver !== 'undefined') {\n resizeObserver = new globalThis.ResizeObserver(scheduleUpdate);\n if (anchorRef.current) resizeObserver.observe(anchorRef.current);\n if (floatingRef.current) resizeObserver.observe(floatingRef.current);\n }\n\n return () => {\n if (frame) window.cancelAnimationFrame(frame);\n window.removeEventListener('scroll', scheduleUpdate, true);\n window.removeEventListener('resize', scheduleUpdate);\n resizeObserver?.disconnect();\n };\n }, [open, update]);\n\n return { anchorRef, floatingRef, style, actualSide, update };\n}\n"]}
@@ -1,7 +1,7 @@
1
1
  import { Slider } from './chunk-OTQ72WX3.js';
2
2
  import { MediaPlayer } from './chunk-PS5INHGC.js';
3
3
  import { Checkbox } from './chunk-KFLDXJEE.js';
4
- import { Select } from './chunk-34LGPMO4.js';
4
+ import { Select } from './chunk-DLBV42JD.js';
5
5
  import { Modal, ModalHeader, ModalTitle, ModalClose, ModalBody, ModalFooter } from './chunk-XMCIXHGH.js';
6
6
  import { Input } from './chunk-YXCE2HSK.js';
7
7
  import { Button } from './chunk-WRYZ2752.js';
@@ -1999,5 +1999,5 @@ var MediaEditor = React6.forwardRef(
1999
1999
  MediaEditor.displayName = "MediaEditor";
2000
2000
 
2001
2001
  export { FillerWordsModal, MediaEditor, SilenceSettingsModal, SpeedMarkerMenu, WordEditorModal };
2002
- //# sourceMappingURL=chunk-I2BKK3AQ.js.map
2003
- //# sourceMappingURL=chunk-I2BKK3AQ.js.map
2002
+ //# sourceMappingURL=chunk-NGLI2MSM.js.map
2003
+ //# sourceMappingURL=chunk-NGLI2MSM.js.map