@bioturing/components 0.45.0 → 0.46.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 (40) hide show
  1. package/dist/components/base-menu/index.d.ts.map +1 -1
  2. package/dist/components/base-menu/item.d.ts.map +1 -1
  3. package/dist/components/base-menu/item.js +6 -13
  4. package/dist/components/base-menu/item.js.map +1 -1
  5. package/dist/components/button/style.css +1 -1
  6. package/dist/components/combobox/component.d.ts +32 -1
  7. package/dist/components/combobox/component.d.ts.map +1 -1
  8. package/dist/components/combobox/component.js +286 -261
  9. package/dist/components/combobox/component.js.map +1 -1
  10. package/dist/components/combobox/style.css +1 -1
  11. package/dist/components/combobox/utils.d.ts +2 -0
  12. package/dist/components/combobox/utils.d.ts.map +1 -0
  13. package/dist/components/combobox/utils.js +10 -0
  14. package/dist/components/combobox/utils.js.map +1 -0
  15. package/dist/components/hooks/useDraggable.d.ts.map +1 -1
  16. package/dist/components/hooks/useDraggable.js +34 -27
  17. package/dist/components/hooks/useDraggable.js.map +1 -1
  18. package/dist/components/popup-panel/component.d.ts +1 -1
  19. package/dist/components/popup-panel/component.d.ts.map +1 -1
  20. package/dist/components/popup-panel/component.js +217 -233
  21. package/dist/components/popup-panel/component.js.map +1 -1
  22. package/dist/components/popup-panel/constants.d.ts +5 -1
  23. package/dist/components/popup-panel/constants.d.ts.map +1 -1
  24. package/dist/components/popup-panel/constants.js +8 -4
  25. package/dist/components/popup-panel/constants.js.map +1 -1
  26. package/dist/components/popup-panel/style.css +1 -1
  27. package/dist/components/popup-panel/types.d.ts +14 -1
  28. package/dist/components/popup-panel/types.d.ts.map +1 -1
  29. package/dist/components/select-trigger/style.css +1 -1
  30. package/dist/components/theme-provider/style.css +1 -1
  31. package/dist/components/truncate/helpers.d.ts +13 -7
  32. package/dist/components/truncate/helpers.d.ts.map +1 -1
  33. package/dist/components/truncate/helpers.js +102 -85
  34. package/dist/components/truncate/helpers.js.map +1 -1
  35. package/dist/stats.html +1 -1
  36. package/dist/tailwind.css +16 -0
  37. package/dist/tokens/and-theme/tokens.d.ts.map +1 -1
  38. package/dist/tokens/and-theme/tokens.js +4 -1
  39. package/dist/tokens/and-theme/tokens.js.map +1 -1
  40. package/package.json +3 -3
@@ -1,7 +1,11 @@
1
- const m = 4;
2
- var r = /* @__PURE__ */ ((x) => (x.xsmall = "320px", x.small = "400px", x.medium = "480px", x.large = "640px", x.xlarge = "840px", x))(r || {});
1
+ const E = 4;
2
+ var t = /* @__PURE__ */ ((_) => (_.xsmall = "320px", _.small = "400px", _.medium = "480px", _.large = "640px", _.xlarge = "840px", _.fit = "fit-content", _))(t || {});
3
+ const x = 20, O = 10, A = 8;
3
4
  export {
4
- m as DEFAULT_SIDE_OFFSET,
5
- r as PopupPanelSize
5
+ E as DEFAULT_SIDE_OFFSET,
6
+ O as POPUP_PANEL_ARROW_HEIGHT,
7
+ A as POPUP_PANEL_ARROW_SIDE_OFFSET,
8
+ x as POPUP_PANEL_ARROW_WIDTH,
9
+ t as PopupPanelSize
6
10
  };
7
11
  //# sourceMappingURL=constants.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","sources":["../../../src/components/popup-panel/constants.ts"],"sourcesContent":["export const DEFAULT_SIDE_OFFSET = 4;\n\n// Size map for predefined modal sizes\nexport enum PopupPanelSize {\n xsmall = \"320px\",\n small = \"400px\",\n medium = \"480px\",\n large = \"640px\",\n xlarge = \"840px\",\n}\n"],"names":["DEFAULT_SIDE_OFFSET","PopupPanelSize"],"mappings":"AAAO,MAAMA,IAAsB;AAG5B,IAAKC,sBAAAA,OACVA,EAAA,SAAS,SACTA,EAAA,QAAQ,SACRA,EAAA,SAAS,SACTA,EAAA,QAAQ,SACRA,EAAA,SAAS,SALCA,IAAAA,KAAA,CAAA,CAAA;"}
1
+ {"version":3,"file":"constants.js","sources":["../../../src/components/popup-panel/constants.ts"],"sourcesContent":["export const DEFAULT_SIDE_OFFSET = 4;\n\n// Size map for predefined modal sizes\nexport enum PopupPanelSize {\n xsmall = \"320px\",\n small = \"400px\",\n medium = \"480px\",\n large = \"640px\",\n xlarge = \"840px\",\n fit = \"fit-content\",\n}\n\nexport const POPUP_PANEL_ARROW_WIDTH = 20;\nexport const POPUP_PANEL_ARROW_HEIGHT = 10;\nexport const POPUP_PANEL_ARROW_SIDE_OFFSET = 8;\n"],"names":["DEFAULT_SIDE_OFFSET","PopupPanelSize","POPUP_PANEL_ARROW_WIDTH","POPUP_PANEL_ARROW_HEIGHT","POPUP_PANEL_ARROW_SIDE_OFFSET"],"mappings":"AAAO,MAAMA,IAAsB;AAG5B,IAAKC,sBAAAA,OACVA,EAAA,SAAS,SACTA,EAAA,QAAQ,SACRA,EAAA,SAAS,SACTA,EAAA,QAAQ,SACRA,EAAA,SAAS,SACTA,EAAA,MAAM,eANIA,IAAAA,KAAA,CAAA,CAAA;AASL,MAAMC,IAA0B,IAC1BC,IAA2B,IAC3BC,IAAgC;"}
@@ -1 +1 @@
1
- @layer components{.ds-popup-panel-root{z-index:var(--ds-z-index-popover)}.ds-popup-panel{box-shadow:var(--ds-box-shadow-secondary);border-radius:var(--ds-border-radius);background:var(--ds-color-bg-elevated);list-style:none;color:var(--ds-color-text);font-size:var(--ds-font-size);font-family:var(--ds-font-family);transition-property:transform,scale,opacity;transition-duration:.2s;transition-timing-function:var(--ds-motion-ease-out);transform-origin:var(--transform-origin);width:min(var(--size-width),var(--available-width));max-width:var(--available-width);max-height:var(--available-height);height:max-content;display:flex;flex-direction:column}.ds-popup-panel[data-ending-style],.ds-popup-panel[data-starting-style]{transform:scale(.9);opacity:0}.ds-popup-panel:focus{outline:none}.ds-popup-panel-header{border-bottom:1px solid var(--ds-color-split);margin-bottom:0;padding:calc(var(--ds-popup-panel-padding) / 2) var(--ds-popup-panel-padding);flex:0}.ds-popup-panel-title-wrapper{font-weight:500;font-size:var(--ds-font-size);line-height:var(--ds-line-height);color:var(--ds-color-text)}.ds-popup-panel-footer{border-top:1px solid var(--ds-color-split);margin-top:0;padding:calc(var(--ds-popup-panel-padding) / 2) var(--ds-popup-panel-padding);flex:0}.ds-popup-panel-content{display:flex;flex-direction:column;flex:1;overflow:auto}.ds-popup-panel-content .ds-popup-panel-content-inner{flex:1;padding:var(--ds-popup-panel-padding)}}
1
+ @layer components{.ds-popup-panel-root{z-index:var(--ds-z-index-popover)}.ds-popup-panel-root.ds-popup-panel-z-index-panel{z-index:var(--ds-z-index-panel)}.ds-popup-panel{position:relative;box-shadow:var(--ds-box-shadow-secondary);border-radius:var(--ds-border-radius);background:var(--ds-color-bg-elevated);list-style:none;color:var(--ds-color-text);font-size:var(--ds-font-size);font-family:var(--ds-font-family);transition-property:transform,scale,opacity;transition-duration:.2s;transition-timing-function:var(--ds-motion-ease-out);transform-origin:var(--transform-origin);width:min(var(--size-width),var(--available-width));max-width:var(--available-width);max-height:var(--available-height);height:max-content;display:flex;flex-direction:column}.ds-popup-panel[data-ending-style],.ds-popup-panel[data-starting-style]{transform:scale(.9);opacity:0}.ds-popup-panel:focus{outline:none}.ds-popup-panel[data-dragging],.ds-popup-panel[data-resizing]{transition:none}.ds-popup-panel-arrow{display:flex;width:var(--popup-panel-arrow-width);height:var(--popup-panel-arrow-height);color:var(--ds-color-bg-elevated)}.ds-popup-panel-arrow[data-side=top]{bottom:-8px;rotate:180deg}.ds-popup-panel-arrow[data-side=bottom]{top:-8px;rotate:0deg}.ds-popup-panel-arrow[data-side=left]{right:-13px;rotate:90deg}.ds-popup-panel-arrow[data-side=right]{left:-13px;rotate:-90deg}.ds-popup-panel-arrow-svg{display:block}.ds-popup-panel-arrow-fill{fill:var(--ds-color-bg-elevated)}.ds-popup-panel-arrow-outer-stroke{fill:var(--ds-modal-color-border)}.ds-popup-panel-arrow-inner-stroke,.dark .ds-popup-panel-arrow-outer-stroke{fill:none}.dark .ds-popup-panel-arrow-inner-stroke{fill:var(--ds-modal-color-border)}.ds-popup-panel-header{border-bottom:1px solid var(--ds-color-split);margin-bottom:0;padding:calc(var(--ds-popup-panel-padding) / 2) var(--ds-popup-panel-padding);flex:0}.ds-popup-panel-title-wrapper{font-weight:500;font-size:var(--ds-font-size);line-height:var(--ds-line-height);color:var(--ds-color-text)}.ds-popup-panel-footer{border-top:1px solid var(--ds-color-split);margin-top:0;padding:calc(var(--ds-popup-panel-padding) / 2) var(--ds-popup-panel-padding);flex:0}.ds-popup-panel-content{flex:1;min-height:0;overflow:auto;padding:var(--ds-popup-panel-padding)}}
@@ -30,6 +30,11 @@ export interface PopupPanelProps extends Omit<React.ComponentPropsWithRef<"div">
30
30
  afterCloseButton?: React.ReactNode;
31
31
  /** Content to display after the title */
32
32
  afterTitle?: React.ReactNode;
33
+ /**
34
+ * Whether to show the popup arrow
35
+ * @default false
36
+ */
37
+ arrow?: boolean;
33
38
  /**
34
39
  * Predefined sizes for the popup panel
35
40
  * - xsmall: 320px
@@ -76,6 +81,7 @@ export interface PopupPanelProps extends Omit<React.ComponentPropsWithRef<"div">
76
81
  root?: string;
77
82
  trigger?: string;
78
83
  popup?: string;
84
+ arrow?: string;
79
85
  header?: string;
80
86
  title?: string;
81
87
  content?: string;
@@ -112,7 +118,7 @@ export interface PopupPanelProps extends Omit<React.ComponentPropsWithRef<"div">
112
118
  * Reference element to offset the popup panel from
113
119
  * If not provided, the panel will be positioned relative to the trigger element
114
120
  */
115
- offsetFrom?: RefObject<HTMLElement>;
121
+ offsetFrom?: RefObject<HTMLElement | null>;
116
122
  /**
117
123
  * Whether the trigger should act as a native button element.
118
124
  * Set to false when using non-button elements as trigger
@@ -120,5 +126,12 @@ export interface PopupPanelProps extends Omit<React.ComponentPropsWithRef<"div">
120
126
  * @default true
121
127
  */
122
128
  nativeButton?: boolean;
129
+ /**
130
+ * The z-index of the popup panel.
131
+ * - 'popup': higher z-index (default)
132
+ * - 'panel': lower z-index
133
+ * @default "popup"
134
+ */
135
+ zIndex?: "popup" | "panel";
123
136
  }
124
137
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/components/popup-panel/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/components/popup-panel/types.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- @layer components{.ds-select-trigger{position:relative;display:inline-flex;align-items:center;cursor:pointer;width:100%;background-color:var(--ds-control-color-bg);border:1px solid var(--ds-control-color-border);border-radius:var(--ds-control-border-radius);transition:var(--ds-control-transition);text-align:left}.ds-select-trigger:focus,.ds-select-trigger:focus-visible{outline:none}.ds-select-trigger:hover:not(.ds-select-trigger-disabled){border-color:var(--ds-control-color-border-hover)}.ds-select-trigger:focus,.ds-select-trigger:focus-visible,.ds-select-trigger-focused{border:var(--ds-control-border-active);box-shadow:var(--ds-control-shadow-active)}.ds-select-trigger-open{border:var(--ds-control-border-active)}.ds-select-trigger-disabled{background-color:var(--ds-control-color-bg-disabled);cursor:not-allowed;color:var(--ds-control-color-text-disabled)}.ds-select-trigger-disabled .ds-select-trigger-text{cursor:not-allowed}.ds-select-trigger-error{border:var(--ds-control-border-error-active)}.ds-select-trigger-error:focus,.ds-select-trigger-error:focus-visible,.ds-select-trigger-error.ds-select-trigger-focused{border:var(--ds-control-border-error-active);box-shadow:var(--ds-control-shadow-error-active)}.ds-select-trigger-warning{border:var(--ds-control-border-warning-active)}.ds-select-trigger-warning:focus,.ds-select-trigger-warning:focus-visible,.ds-select-trigger-warning.ds-select-trigger-focused{border:var(--ds-control-border-warning-active);box-shadow:var(--ds-control-shadow-warning-active)}.ds-select-trigger-value{flex:1;color:var(--ds-control-color-text);overflow:hidden;white-space:nowrap;text-overflow:ellipsis;text-align:left}.ds-select-trigger-value-with-prefix{display:flex;align-items:center;gap:8px;flex:1;min-width:0}.ds-select-trigger-placeholder{flex:1;color:var(--ds-control-color-text-placeholder);overflow:hidden;white-space:nowrap;text-overflow:ellipsis;text-align:left}.ds-select-trigger-suffix{display:flex;align-items:center;justify-content:center;width:var(--ds-control-icon-size);height:var(--ds-control-icon-size);position:relative;font-size:var(--ds-control-icon-size);flex-shrink:0}.ds-select-trigger-arrow,.ds-select-trigger-clear{position:absolute;top:50%;right:var(--ds-trigger-padding-inline);transform:translateY(-50%);display:flex;align-items:center;justify-content:center;color:var(--ds-control-color-icon);width:var(--ds-control-icon-size);height:var(--ds-control-icon-size)}.ds-select-trigger-arrow-icon{display:flex;align-items:center;justify-content:center;transition:transform .2s ease}.ds-select-trigger-open .ds-select-trigger-arrow-icon{transform:rotate(180deg)}.ds-select-trigger-clear{pointer-events:none;opacity:0;transition:opacity .2s ease}.ds-select-trigger-clear:hover{color:var(--ds-control-color-icon-hover)}.ds-select-trigger-clear-icon{display:flex;align-items:center;justify-content:center}.ds-select-trigger-allow-clear.ds-select-trigger-has-value:hover .ds-select-trigger-arrow{opacity:0;pointer-events:none}.ds-select-trigger-allow-clear.ds-select-trigger-has-value:hover .ds-select-trigger-clear{pointer-events:auto;opacity:1}.ds-select-trigger-small{--ds-trigger-padding: var(--ds-control-padding-small);--ds-trigger-padding-inline: var(--ds-control-padding-inline-small);--ds-trigger-padding-block: var(--ds-control-padding-block-small);min-height:var(--ds-control-min-height-small);line-height:var(--ds-control-line-height)}.ds-select-trigger-middle{--ds-trigger-padding: var(--ds-control-padding-middle);--ds-trigger-padding-inline: var(--ds-control-padding-inline-middle);--ds-trigger-padding-block: var(--ds-control-padding-block-middle);min-height:var(--ds-control-min-height-middle);line-height:var(--ds-control-line-height)}.ds-select-trigger-large{--ds-trigger-padding: var(--ds-control-padding-large);--ds-trigger-padding-inline: var(--ds-control-padding-inline-large);--ds-trigger-padding-block: var(--ds-control-padding-block-large);min-height:var(--ds-control-min-height-large);line-height:var(--ds-control-line-height)}.ds-select-trigger-content{display:flex;align-items:center;flex:1;min-width:0;overflow:hidden;padding:var(--ds-trigger-padding-block) calc(var(--ds-trigger-padding-inline) + 1rem) var(--ds-trigger-padding-block) var(--ds-trigger-padding-inline)}}
1
+ @layer components{.ds-select-trigger{position:relative;display:inline-flex;align-items:center;cursor:pointer;width:100%;background-color:var(--ds-control-color-bg);border:1px solid var(--ds-control-color-border);border-radius:var(--ds-control-border-radius);transition:var(--ds-control-transition);text-align:left}.ds-select-trigger:focus,.ds-select-trigger:focus-visible{outline:none}.ds-select-trigger:hover:not(.ds-select-trigger-disabled){border-color:var(--ds-control-color-border-hover)}.ds-select-trigger:focus,.ds-select-trigger:focus-visible,.ds-select-trigger-focused{border:var(--ds-control-border-active);box-shadow:var(--ds-control-shadow-active)}.ds-select-trigger-open{border:var(--ds-control-border-active)}.ds-select-trigger-disabled{background-color:var(--ds-control-color-bg-disabled);cursor:not-allowed;color:var(--ds-control-color-text-disabled)}.ds-select-trigger-disabled .ds-select-trigger-text{cursor:not-allowed}.ds-select-trigger-error{border:var(--ds-control-border-error-active)}.ds-select-trigger-error:focus,.ds-select-trigger-error:focus-visible,.ds-select-trigger-error.ds-select-trigger-focused{border:var(--ds-control-border-error-active);box-shadow:var(--ds-control-shadow-error-active)}.ds-select-trigger-warning{border:var(--ds-control-border-warning-active)}.ds-select-trigger-warning:focus,.ds-select-trigger-warning:focus-visible,.ds-select-trigger-warning.ds-select-trigger-focused{border:var(--ds-control-border-warning-active);box-shadow:var(--ds-control-shadow-warning-active)}.ds-select-trigger-value{flex:1;color:var(--ds-control-color-text);overflow:hidden;white-space:nowrap;text-overflow:ellipsis;text-align:left}.ds-select-trigger-value-with-prefix{display:flex;align-items:center;gap:8px;flex:1;min-width:0}.ds-select-trigger-placeholder{flex:1;color:var(--ds-control-color-text-placeholder);overflow:hidden;white-space:nowrap;text-overflow:ellipsis;text-align:left}.ds-select-trigger-suffix{display:flex;align-items:center;justify-content:center;width:var(--ds-control-icon-size);height:var(--ds-control-icon-size);position:relative;font-size:var(--ds-control-icon-size);flex-shrink:0}.ds-select-trigger-arrow,.ds-select-trigger-clear{position:absolute;top:50%;right:var(--ds-trigger-padding-inline);transform:translateY(-50%);display:flex;align-items:center;justify-content:center;color:var(--ds-control-color-icon);width:var(--ds-control-icon-size);height:var(--ds-control-icon-size)}.ds-select-trigger-arrow-icon{display:flex;align-items:center;justify-content:center;transition:transform .2s ease}.ds-select-trigger-open .ds-select-trigger-arrow-icon{transform:rotate(180deg)}.ds-select-trigger-clear{pointer-events:none;opacity:0;transition:opacity .2s ease}.ds-select-trigger-clear:hover{color:var(--ds-control-color-icon-hover)}.ds-select-trigger-clear-icon{display:flex;align-items:center;justify-content:center}.ds-select-trigger-allow-clear.ds-select-trigger-has-value:hover .ds-select-trigger-arrow{opacity:0;pointer-events:none}.ds-select-trigger-allow-clear.ds-select-trigger-has-value:hover .ds-select-trigger-clear{pointer-events:auto;opacity:1}.ds-select-trigger-small{--ds-trigger-padding: var(--ds-control-padding-small);--ds-trigger-padding-inline: var(--ds-control-padding-inline-small);--ds-trigger-padding-block: var(--ds-control-padding-block-small);min-height:var(--ds-control-min-height-small);line-height:var(--ds-control-line-height)}.ds-select-trigger-middle{--ds-trigger-padding: var(--ds-control-padding-middle);--ds-trigger-padding-inline: var(--ds-control-padding-inline-middle);--ds-trigger-padding-block: var(--ds-control-padding-block-middle);min-height:var(--ds-control-min-height-middle);line-height:var(--ds-control-line-height)}.ds-select-trigger-large{--ds-trigger-padding: var(--ds-control-padding-large);--ds-trigger-padding-inline: var(--ds-control-padding-inline-large);--ds-trigger-padding-block: var(--ds-control-padding-block-large);min-height:var(--ds-control-min-height-large);line-height:var(--ds-control-line-height)}.ds-select-trigger-content{display:flex;align-items:center;flex:1;min-width:0;overflow:hidden;padding:var(--ds-trigger-padding-block) calc(var(--ds-trigger-padding-inline) + 1rem) var(--ds-trigger-padding-block) var(--ds-trigger-padding-inline);max-width:100%}.ds-select-trigger-text{min-width:0;max-width:100%}}
@@ -1 +1 @@
1
- @layer components{@keyframes ds-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.ds-theme-provider{--ds-modal-padding: 24px;--ds-modal-edge-padding: 16px;--ds-popup-panel-padding: 16px;--ds-scrollbar-width: auto;--ds-scrollbar-width-legacy: 15;--ds-box-shadow-popover-arrow: 0px 0px 1px 0px var(--ds-modal-color-border), 2px 2px 5px rgba(0, 0, 0, .05);--ds-control-border-radius: 6px;--ds-control-transition: all .2s;--ds-control-padding-small: 1px 8px;--ds-control-padding-middle: 5px 12px;--ds-control-padding-large: 9px 12px;--ds-control-padding-inline-small: 8px;--ds-control-padding-block-small: 1px;--ds-control-padding-inline-middle: 12px;--ds-control-padding-block-middle: 5px;--ds-control-padding-inline-large: 12px;--ds-control-padding-block-large: 9px;--ds-control-min-height-small: 24px;--ds-control-min-height-middle: 32px;--ds-control-min-height-large: 40px;--ds-control-line-height: 20px;--ds-control-color-border-hover: var(--ds-color-primary-hover);--ds-control-color-border-focus: var(--ds-color-primary);--ds-control-color-bg-disabled: var(--ds-color-bg-container-disabled);--ds-control-color-text-disabled: var(--ds-color-text-disabled);--ds-control-icon-size: 12px;--ds-control-color-bg: var(--ds-color-bg-container);--ds-control-color-border: var(--ds-color-border);--ds-control-color-border-active: var(--ds-color-primary);--ds-control-color-border-error-active: var(--ds-color-error);--ds-control-color-border-warning-active: var(--ds-color-warning);--ds-control-color-icon: var(--ds-color-text-quaternary);--ds-control-color-icon-hover: var(--ds-color-icon-hover);--ds-control-border: 1px solid var(--ds-control-color-border);--ds-control-border-active: 1px solid var(--ds-control-color-border-active);--ds-control-border-error-active: 1px solid var(--ds-control-color-border-error-active);--ds-control-border-warning-active: 1px solid var(--ds-control-color-border-warning-active);--ds-control-shadow-active: 0 0 0 2px color-mix(in oklab, var(--ds-color-primary) 20%, transparent);--ds-form-label-required-mark-color: var(--ds-color-error);--ds-control-shadow-error-active: 0 0 0 2px color-mix(in oklab, var(--ds-color-error) 20%, transparent);--ds-control-shadow-warning-active: 0 0 0 2px color-mix(in oklab, var(--ds-color-warning) 20%, transparent);--ds-control-color-text-placeholder: var(--ds-color-text-placeholder);--ds-button-bg-secondary: #fafafa;--ds-button-bg-gradient-top: rgba(0, 0, 0, .02);--ds-button-bg-gradient-bottom: rgba(255, 255, 255, 0);--ds-button-bg-gradient-primary-top: rgba(255, 255, 255, .07);--ds-button-bg-gradient-primary-bottom: rgba(255, 255, 255, 0);--ds-button-shadow-default: 0 1px 1px 0 rgba(0, 0, 0, .05);--ds-button-shadow-default-inner: inset 0 1.5px 0 1px #ffffff;--ds-button-shadow-solid: 0 1px 1px 0 rgba(0, 0, 0, .12);--ds-button-shadow-solid-hover: 0 1px 1px 0 rgba(0, 0, 0, .12);--ds-button-shadow-solid-active: 0 1px 1px 0 rgba(0, 0, 0, .12);--ds-button-shadow-solid-inner: inset 0 1.5px 0 1px rgba(255, 255, 255, .12);--ds-inter: "Inter", Helvetica, Arial, sans-serif;--ds-roboto-mono: "Roboto Mono", Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--ds-animate-spin: ds-spin 1s linear infinite;--ds-z-index-base: 0;--ds-z-index-sticky-element: 520;--ds-z-index-scrollbar: 530;--ds-z-index-modal: 1000;--ds-z-index-modal-mask: 1000;--ds-z-index-message: 1010;--ds-z-index-notification: 1010;--ds-z-index-popover: 1030;--ds-z-index-dropdown: 1050;--ds-z-index-picker: 1050;--ds-z-index-popconfirm: 1060;--ds-z-index-tooltip: 1070;--ds-z-index-toast: 2000;--ds-segment-color-bg-active: #ffffff;--ds-scrollbar-color-thumb: rgba(0, 0, 0, .2);--ds-scrollbar-color-track: rgba(0, 0, 0, 0);--ds-color-base-solid: #000000;--ds-color-table-fixed-column-shadow: rgb(0 0 0 / 10%);--ds-modal-color-border: rgba(0, 0, 0, .24)}@supports (font-variation-settings: normal){.ds-theme-provider{--ds-inter: "InterVariable", Inter, Helvetica, Arial, sans-serif;--ds-roboto-mono: "Roboto Mono Variable", Roboto Mono, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;font-optical-sizing:auto}}.ds-theme-provider.dark{--ds-modal-color-border: rgba(255, 255, 255, .55);--ds-segment-color-bg-active: #424248;--ds-scrollbar-color-thumb: rgba(255, 255, 255, .2);--ds-scrollbar-color-track: rgba(0, 0, 0, 0);--ds-color-base-solid: #ffffff;--ds-color-table-fixed-column-shadow: rgb(0 0 0 / 20%);--ds-button-bg-secondary: hsl(240, 6.5%, 17%);--ds-button-bg-gradient-top: rgba(255, 255, 255, .06);--ds-button-bg-gradient-bottom: rgba(255, 255, 255, 0);--ds-button-bg-gradient-primary-top: rgba(255, 255, 255, .12);--ds-button-bg-gradient-primary-bottom: rgba(255, 255, 255, 0);--ds-button-shadow-default: 0 1px 1px 0 rgba(0, 0, 0, .05);--ds-button-shadow-default-inner: none;--ds-button-shadow-solid: 0 1px 1px 0 rgba(0, 0, 0, .12);--ds-button-shadow-solid-hover: 0 1px 1px 0 rgba(0, 0, 0, .12);--ds-button-shadow-solid-active: 0 1px 1px 0 rgba(0, 0, 0, .12);--ds-button-shadow-solid-inner: inset 0 1.5px 0 1px rgba(255, 255, 255, .16)}}
1
+ @layer components{@keyframes ds-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.ds-theme-provider{--ds-modal-padding: 24px;--ds-modal-edge-padding: 16px;--ds-popup-panel-padding: 16px;--ds-scrollbar-width: auto;--ds-scrollbar-width-legacy: 15;--ds-box-shadow-popover-arrow: 0px 0px 1px 0px var(--ds-modal-color-border), 2px 2px 5px rgba(0, 0, 0, .05);--ds-control-border-radius: 6px;--ds-control-transition: all .2s;--ds-control-padding-small: 1px 8px;--ds-control-padding-middle: 5px 12px;--ds-control-padding-large: 9px 12px;--ds-control-padding-inline-small: 8px;--ds-control-padding-block-small: 1px;--ds-control-padding-inline-middle: 12px;--ds-control-padding-block-middle: 5px;--ds-control-padding-inline-large: 12px;--ds-control-padding-block-large: 9px;--ds-control-min-height-small: 24px;--ds-control-min-height-middle: 32px;--ds-control-min-height-large: 40px;--ds-control-line-height: 20px;--ds-control-color-border-hover: var(--ds-color-primary-hover);--ds-control-color-border-focus: var(--ds-color-primary);--ds-control-color-bg-disabled: var(--ds-color-bg-container-disabled);--ds-control-color-text-disabled: var(--ds-color-text-disabled);--ds-control-icon-size: 12px;--ds-control-color-bg: var(--ds-color-bg-container);--ds-control-color-border: var(--ds-color-border);--ds-control-color-border-active: var(--ds-color-primary);--ds-control-color-border-error-active: var(--ds-color-error);--ds-control-color-border-warning-active: var(--ds-color-warning);--ds-control-color-icon: var(--ds-color-text-quaternary);--ds-control-color-icon-hover: var(--ds-color-icon-hover);--ds-control-border: 1px solid var(--ds-control-color-border);--ds-control-border-active: 1px solid var(--ds-control-color-border-active);--ds-control-border-error-active: 1px solid var(--ds-control-color-border-error-active);--ds-control-border-warning-active: 1px solid var(--ds-control-color-border-warning-active);--ds-control-shadow-active: 0 0 0 2px color-mix(in oklab, var(--ds-color-primary) 20%, transparent);--ds-form-label-required-mark-color: var(--ds-color-error);--ds-control-shadow-error-active: 0 0 0 2px color-mix(in oklab, var(--ds-color-error) 20%, transparent);--ds-control-shadow-warning-active: 0 0 0 2px color-mix(in oklab, var(--ds-color-warning) 20%, transparent);--ds-control-color-text-placeholder: var(--ds-color-text-placeholder);--ds-button-bg-secondary: #fafafa;--ds-button-bg-gradient-top: rgba(0, 0, 0, .02);--ds-button-bg-gradient-bottom: rgba(255, 255, 255, 0);--ds-button-bg-gradient-primary-top: rgba(255, 255, 255, .07);--ds-button-bg-gradient-primary-bottom: rgba(255, 255, 255, 0);--ds-button-shadow-default: 0 0 0 0 transparent;--ds-button-shadow-default-inner: inset 0 1px 0 1px #ffffff;--ds-button-shadow-solid: 0 0 0 0 transparent;--ds-button-shadow-solid-hover: 0 0 0 0 transparent;--ds-button-shadow-solid-active: 0 0 0 0 transparent;--ds-button-shadow-solid-inner: inset 0 1px 0 1px rgba(255, 255, 255, .12);--ds-color-primary-fg: hsl(217 80% 40%);--ds-color-primary-fg-hover: hsl(217 80% 55%);--ds-color-primary-fg-active: hsl(217 80% 30%);--ds-color-error-fg: hsl(5 68% 45%);--ds-color-error-fg-hover: hsl(5 68% 50%);--ds-color-error-fg-active: hsl(5 68% 40%);--ds-inter: "Inter", Helvetica, Arial, sans-serif;--ds-roboto-mono: "Roboto Mono", Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--ds-animate-spin: ds-spin 1s linear infinite;--ds-z-index-base: 0;--ds-z-index-sticky-element: 520;--ds-z-index-scrollbar: 530;--ds-z-index-panel: 540;--ds-z-index-modal: 1000;--ds-z-index-modal-mask: 1000;--ds-z-index-message: 1010;--ds-z-index-notification: 1010;--ds-z-index-popover: 1030;--ds-z-index-popup: 1030;--ds-z-index-dropdown: 1050;--ds-z-index-picker: 1050;--ds-z-index-popconfirm: 1060;--ds-z-index-tooltip: 1070;--ds-z-index-toast: 2000;--ds-segment-color-bg-active: #ffffff;--ds-scrollbar-color-thumb: rgba(0, 0, 0, .2);--ds-scrollbar-color-track: rgba(0, 0, 0, 0);--ds-color-base-solid: #000000;--ds-color-table-fixed-column-shadow: rgb(0 0 0 / 10%);--ds-modal-color-border: rgba(0, 0, 0, .07)}@supports (font-variation-settings: normal){.ds-theme-provider{--ds-inter: "InterVariable", Inter, Helvetica, Arial, sans-serif;--ds-roboto-mono: "Roboto Mono Variable", Roboto Mono, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;font-optical-sizing:auto}}.ds-theme-provider.dark{--ds-modal-color-border: rgba(255, 255, 255, .1);--ds-segment-color-bg-active: #424248;--ds-scrollbar-color-thumb: rgba(255, 255, 255, .2);--ds-scrollbar-color-track: rgba(0, 0, 0, 0);--ds-color-base-solid: #ffffff;--ds-color-table-fixed-column-shadow: rgb(0 0 0 / 20%);--ds-button-bg-secondary: hsl(240, 6.5%, 17%);--ds-button-bg-gradient-top: rgba(255, 255, 255, .03);--ds-button-bg-gradient-bottom: rgba(255, 255, 255, 0);--ds-button-bg-gradient-primary-top: rgba(255, 255, 255, .12);--ds-button-bg-gradient-primary-bottom: rgba(255, 255, 255, 0);--ds-button-shadow-default: 0 0 0 0 transparent;--ds-button-shadow-default-inner: 0 0 0 0 transparent;--ds-button-shadow-solid: 0 0 0 0 transparent;--ds-button-shadow-solid-hover: 0 0 0 0 transparent;--ds-button-shadow-solid-active: 0 0 0 0 transparent;--ds-button-shadow-solid-inner: inset 0 1px 0 1px rgba(255, 255, 255, .14);--ds-color-primary-fg: hsl(211 95% 60%);--ds-color-primary-fg-hover: hsl(211 95% 65%);--ds-color-primary-fg-active: hsl(211 95% 58%);--ds-color-error-fg: hsl(4 72% 59%);--ds-color-error-fg-hover: hsl(4 72% 64%);--ds-color-error-fg-active: hsl(4 72% 56%)}}
@@ -7,14 +7,20 @@ import { default as React } from 'react';
7
7
  export declare function findClosestInlineFlexParent(element: HTMLElement): HTMLElement | null;
8
8
  export declare function getFlexRemainingSpace(flexContainer: HTMLElement, ignoreElement?: HTMLElement | ((e: HTMLElement) => boolean)): number;
9
9
  /**
10
- * Measures text width with optional render function for styled content
11
- * @param container - The container element to clone styles from
12
- * @param renderText - Optional render function to apply styling to text before measurement
10
+ * Computes a middle-truncated version of `text` that fits within
11
+ * `container.clientWidth` pixels.
12
+ *
13
+ * Uses a binary search over the total number of characters to keep.
14
+ * Plain text uses canvas measurement; custom `renderText` falls back to DOM
15
+ * measurement because styled markup can change the rendered width.
16
+ *
17
+ * @param text - The original string.
18
+ * @param ellipsis - Separator to insert at the truncation point (e.g. "…").
19
+ * @param container - The element whose `clientWidth` sets the budget and
20
+ * whose computed font is used for measurement.
21
+ * @param renderText - Optional custom renderer used for styled text measurement.
22
+ * @returns The original string if it fits, or a middle-truncated string.
13
23
  */
14
- export declare const measureText: (container: HTMLElement, renderText?: ((text: string) => React.ReactNode) | null) => {
15
- measure: (text: string) => number;
16
- destroy: () => void;
17
- };
18
24
  export declare const getMiddleTruncatedString: (text: string, ellipsis: string, container: HTMLElement, renderText?: ((text: string) => React.ReactNode) | null) => string;
19
25
  export declare const createMeasurementClone: (text: string, container: HTMLElement) => HTMLSpanElement;
20
26
  export declare const checkIfTextTruncated: (text: string, container: HTMLElement, availableHeight?: number) => boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../src/components/truncate/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B;;;;GAIG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,WAAW,GACnB,WAAW,GAAG,IAAI,CAqBpB;AAED,wBAAgB,qBAAqB,CACnC,aAAa,EAAE,WAAW,EAC1B,aAAa,GAAE,WAAW,GAAG,CAAC,CAAC,CAAC,EAAE,WAAW,KAAK,OAAO,CAAQ,UA2ClE;AAKD;;;;GAIG;AACH,eAAO,MAAM,WAAW,GACtB,WAAW,WAAW,EACtB,aAAa,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,KAAK,CAAC,SAAS,CAAC,GAAG,IAAI;oBAwBrC,MAAM;;CA0DzB,CAAC;AAEF,eAAO,MAAM,wBAAwB,GACnC,MAAM,MAAM,EACZ,UAAU,MAAM,EAChB,WAAW,WAAW,EACtB,aAAa,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,KAAK,CAAC,SAAS,CAAC,GAAG,IAAI,KACtD,MAgEF,CAAC;AAGF,eAAO,MAAM,sBAAsB,GACjC,MAAM,MAAM,EACZ,WAAW,WAAW,oBAavB,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAC/B,MAAM,MAAM,EACZ,WAAW,WAAW,EACtB,kBAAkB,MAAM,YAQzB,CAAC;AAEF,eAAO,MAAM,wBAAwB,GAAI,WAAW,WAAW,WAiB9D,CAAC;AAEF,eAAO,MAAM,uBAAuB,GAAI,WAAW,WAAW,WAiB7D,CAAC;AAGF,MAAM,MAAM,YAAY,GAAG,YAAY,GAAG,UAAU,GAAG,MAAM,CAAC;AAE9D,MAAM,WAAW,oBAAoB;IACnC,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,eAAO,MAAM,uBAAuB,GAAI,WAAW,WAAW,KAAG,OAEhE,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAChC,WAAW,WAAW,EACtB,kBAAkB,MAAM,KACvB,OAGF,CAAC;AAEF,eAAO,MAAM,aAAa,GACxB,WAAW,WAAW,EACtB,UAAS,oBAAyB,KACjC,OAyCF,CAAC"}
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../src/components/truncate/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B;;;;GAIG;AACH,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,WAAW,GAAG,WAAW,GAAG,IAAI,CAqBpF;AAED,wBAAgB,qBAAqB,CACnC,aAAa,EAAE,WAAW,EAC1B,aAAa,GAAE,WAAW,GAAG,CAAC,CAAC,CAAC,EAAE,WAAW,KAAK,OAAO,CAAQ,UA6BlE;AAgJD;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,wBAAwB,GACnC,MAAM,MAAM,EACZ,UAAU,MAAM,EAChB,WAAW,WAAW,EACtB,aAAa,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,KAAK,CAAC,SAAS,CAAC,GAAG,IAAI,KACtD,MAmBF,CAAC;AAGF,eAAO,MAAM,sBAAsB,GAAI,MAAM,MAAM,EAAE,WAAW,WAAW,oBAY1E,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAC/B,MAAM,MAAM,EACZ,WAAW,WAAW,EACtB,kBAAkB,MAAM,YAQzB,CAAC;AAEF,eAAO,MAAM,wBAAwB,GAAI,WAAW,WAAW,WAW9D,CAAC;AAEF,eAAO,MAAM,uBAAuB,GAAI,WAAW,WAAW,WAW7D,CAAC;AAGF,MAAM,MAAM,YAAY,GAAG,YAAY,GAAG,UAAU,GAAG,MAAM,CAAC;AAE9D,MAAM,WAAW,oBAAoB;IACnC,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,eAAO,MAAM,uBAAuB,GAAI,WAAW,WAAW,KAAG,OAEhE,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAChC,WAAW,WAAW,EACtB,kBAAkB,MAAM,KACvB,OAGF,CAAC;AAEF,eAAO,MAAM,aAAa,GACxB,WAAW,WAAW,EACtB,UAAS,oBAAyB,KACjC,OA2CF,CAAC"}
@@ -1,111 +1,128 @@
1
- import v from "react";
2
- import { renderToStaticMarkup as w } from "react-dom/server";
3
- const d = /* @__PURE__ */ new Map(), W = (e, n) => {
4
- const t = document.createElement("span");
5
- t.style.opacity = "0", t.style.position = "absolute", t.style.top = "-1000px", t.style.left = "-1000px", t.style.whiteSpace = "nowrap", t.style.pointerEvents = "none";
6
- const o = e.getBoundingClientRect(), s = e.cloneNode(!0);
7
- return s.style.maxWidth = `${o.width}px`, s.style.position = "absolute", s.style.pointerEvents = "none", s.style.top = "-99px", s.style.left = "-99px", s.style.zIndex = "-1", e.parentElement?.appendChild(s), s.appendChild(t), {
8
- measure: (l) => {
9
- if (n) {
10
- const r = `${l}-styled`;
11
- if (d.has(r))
12
- return d.get(r);
13
- t.innerHTML = "";
14
- const c = n(l);
15
- if (typeof c == "string")
16
- t.innerHTML = c;
17
- else if (v.isValidElement(c))
18
- try {
19
- const i = w(c);
20
- t.innerHTML = i;
21
- } catch {
22
- t.innerText = l;
23
- }
24
- else
25
- t.innerText = l;
26
- const h = t.clientWidth;
27
- if (d.set(r, h), d.size > 100) {
28
- const i = d.keys().next().value;
29
- d.delete(i);
1
+ import f from "react";
2
+ import { renderToStaticMarkup as g } from "react-dom/server";
3
+ let d = null;
4
+ function m() {
5
+ if (!d) {
6
+ const n = document.createElement("canvas").getContext("2d");
7
+ if (!n) throw new Error("Failed to get 2d context from canvas");
8
+ d = n;
9
+ }
10
+ return d;
11
+ }
12
+ function y(t, n, e, o) {
13
+ const r = m();
14
+ return r.font = n, r.letterSpacing = e, r.wordSpacing = o, r.measureText(t).width;
15
+ }
16
+ function w(t) {
17
+ const n = window.getComputedStyle(t);
18
+ return {
19
+ font: `${n.fontStyle} ${n.fontVariant} ${n.fontWeight} ${n.fontSize} ${n.fontFamily}`,
20
+ letterSpacing: n.letterSpacing,
21
+ wordSpacing: n.wordSpacing
22
+ };
23
+ }
24
+ function S(t, n) {
25
+ const e = document.createElement("span");
26
+ e.style.opacity = "0", e.style.position = "absolute", e.style.top = "-1000px", e.style.left = "-1000px", e.style.whiteSpace = "nowrap", e.style.pointerEvents = "none";
27
+ const o = t.getBoundingClientRect(), r = t.cloneNode(!0);
28
+ return r.style.maxWidth = `${o.width}px`, r.style.position = "absolute", r.style.pointerEvents = "none", r.style.top = "-1000px", r.style.left = "-1000px", r.style.zIndex = "-1", t.parentElement?.appendChild(r), r.appendChild(e), {
29
+ measure: (i) => {
30
+ e.innerHTML = "";
31
+ const l = n(i);
32
+ if (typeof l == "string" || typeof l == "number")
33
+ e.textContent = String(l);
34
+ else if (f.isValidElement(l))
35
+ try {
36
+ e.innerHTML = g(l);
37
+ } catch {
38
+ e.textContent = i;
30
39
  }
31
- return h;
32
- }
33
- return t.innerText = l, t.clientWidth;
40
+ else
41
+ e.textContent = i;
42
+ return e.clientWidth;
34
43
  },
35
44
  destroy: () => {
36
- s.removeChild(t), e.parentElement?.removeChild(s);
45
+ e.remove(), r.remove();
37
46
  }
38
47
  };
39
- }, M = (e, n, t, o) => {
40
- if (!e) return e;
41
- const { measure: s, destroy: l } = W(t, o), r = s(e), c = t.clientWidth, h = Math.floor(
42
- c / r * e.length
43
- );
44
- if (r <= c)
45
- return l(), e;
46
- let i = h;
47
- const a = {}, g = 20, b = 4;
48
- for (; Object.values(a).length <= g && !a[i]; ) {
49
- if (i <= 1) {
50
- a[0] = [0, n];
51
- break;
52
- }
53
- const p = e.slice(0, Math.ceil((i - n.length) / 2 - 1)).trimEnd(), H = e.slice(Math.floor((i - n.length) / 2) - i).trimStart(), m = p + n + H, f = s(m);
54
- if (a[i] = [f, m], f >= c)
55
- i = i - 2;
56
- else {
57
- if (c - f < b) break;
58
- i = i + 2;
48
+ }
49
+ function p(t, n, e, o) {
50
+ if (o(t) <= e) return t;
51
+ const r = (s) => {
52
+ if (s === 0) return n;
53
+ const c = Math.floor(s / 2), a = Math.ceil(s / 2);
54
+ return t.slice(0, c).trimEnd() + n + t.slice(t.length - a).trimStart();
55
+ };
56
+ let i = 0, l = t.length;
57
+ for (; i < l; ) {
58
+ const s = Math.ceil((i + l) / 2), c = r(s);
59
+ o(c) <= e ? i = s : l = s - 1;
60
+ }
61
+ return r(i);
62
+ }
63
+ const v = (t, n, e, o) => {
64
+ if (!t) return t;
65
+ const { font: r, letterSpacing: i, wordSpacing: l } = w(e), s = e.clientWidth;
66
+ if (o) {
67
+ const { measure: c, destroy: a } = S(e, o);
68
+ try {
69
+ return p(t, n, s, c);
70
+ } finally {
71
+ a();
59
72
  }
60
73
  }
61
- return l(), Object.values(a).reverse().find(([p]) => p < c)?.[1] ?? Object.values(a)[0][1];
62
- }, C = (e, n) => {
63
- const t = window.getComputedStyle(n), o = document.createElement("span");
64
- return o.style.visibility = "hidden", o.style.position = "absolute", o.style.width = `${n.clientWidth}px`, o.style.fontSize = t.fontSize, o.style.fontFamily = t.fontFamily, o.style.lineHeight = t.lineHeight, o.textContent = e, document.body.appendChild(o), o;
65
- }, S = (e) => {
66
- const n = e.parentElement;
74
+ return p(
75
+ t,
76
+ n,
77
+ s,
78
+ (c) => y(c, r, i, l)
79
+ );
80
+ }, C = (t, n) => {
81
+ const e = window.getComputedStyle(n), o = document.createElement("span");
82
+ return o.style.visibility = "hidden", o.style.position = "absolute", o.style.width = `${n.clientWidth}px`, o.style.fontSize = e.fontSize, o.style.fontFamily = e.fontFamily, o.style.lineHeight = e.lineHeight, o.textContent = t, document.body.appendChild(o), o;
83
+ }, W = (t) => {
84
+ const n = t.parentElement;
67
85
  if (!n) return 0;
68
- const t = window.getComputedStyle(n), o = parseFloat(t.paddingTop) || 0, s = parseFloat(t.paddingBottom) || 0, l = parseFloat(t.borderTopWidth) || 0, r = parseFloat(t.borderBottomWidth) || 0;
69
- return n.clientHeight - o - s - l - r;
70
- }, u = (e) => e.scrollWidth > e.clientWidth, y = (e, n) => {
71
- const t = n ?? (e.clientHeight || e.offsetHeight);
72
- return e.scrollHeight > t;
73
- }, E = (e, n = {}) => {
74
- const { type: t = "horizontal", availableHeight: o, text: s } = n;
75
- if (s) {
76
- const l = C(s, e);
77
- let r = !1;
78
- switch (t) {
86
+ const e = window.getComputedStyle(n), o = parseFloat(e.paddingTop) || 0, r = parseFloat(e.paddingBottom) || 0, i = parseFloat(e.borderTopWidth) || 0, l = parseFloat(e.borderBottomWidth) || 0;
87
+ return n.clientHeight - o - r - i - l;
88
+ }, h = (t) => t.scrollWidth > t.clientWidth, u = (t, n) => {
89
+ const e = n ?? (t.clientHeight || t.offsetHeight);
90
+ return t.scrollHeight > e;
91
+ }, x = (t, n = {}) => {
92
+ const { type: e = "horizontal", availableHeight: o, text: r } = n;
93
+ if (r) {
94
+ const i = C(r, t);
95
+ let l = !1;
96
+ switch (e) {
79
97
  case "horizontal":
80
- r = l.scrollWidth > e.clientWidth;
98
+ l = i.scrollWidth > t.clientWidth;
81
99
  break;
82
100
  case "vertical":
83
- r = o ? l.scrollHeight > o : l.scrollHeight > (e.clientHeight || e.offsetHeight);
101
+ l = o ? i.scrollHeight > o : i.scrollHeight > (t.clientHeight || t.offsetHeight);
84
102
  break;
85
103
  case "both":
86
- r = l.scrollWidth > e.clientWidth || (o ? l.scrollHeight > o : l.scrollHeight > (e.clientHeight || e.offsetHeight));
104
+ l = i.scrollWidth > t.clientWidth || (o ? i.scrollHeight > o : i.scrollHeight > (t.clientHeight || t.offsetHeight));
87
105
  break;
88
106
  }
89
- return document.body.removeChild(l), r;
107
+ return document.body.removeChild(i), l;
90
108
  }
91
- switch (t) {
109
+ switch (e) {
92
110
  case "horizontal":
93
- return u(e);
111
+ return h(t);
94
112
  case "vertical":
95
- return y(e, o);
113
+ return u(t, o);
96
114
  case "both":
97
- return u(e) || y(e, o);
115
+ return h(t) || u(t, o);
98
116
  default:
99
- return u(e);
117
+ return h(t);
100
118
  }
101
119
  };
102
120
  export {
103
- S as calculateAvailableHeight,
104
- u as checkHorizontalOverflow,
105
- E as checkOverflow,
106
- y as checkVerticalOverflow,
121
+ W as calculateAvailableHeight,
122
+ h as checkHorizontalOverflow,
123
+ x as checkOverflow,
124
+ u as checkVerticalOverflow,
107
125
  C as createMeasurementClone,
108
- M as getMiddleTruncatedString,
109
- W as measureText
126
+ v as getMiddleTruncatedString
110
127
  };
111
128
  //# sourceMappingURL=helpers.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.js","sources":["../../../src/components/truncate/helpers.ts"],"sourcesContent":["import React from \"react\";\nimport { renderToStaticMarkup } from \"react-dom/server\";\n\n/**\n * Finds the closest parent element that has inline flex display\n * @param element - The starting HTMLElement\n * @returns The closest inline flex parent or null if not found\n */\nexport function findClosestInlineFlexParent(\n element: HTMLElement\n): HTMLElement | null {\n if (!element) return null;\n\n let currentElement = element.parentElement;\n let attempts = 0;\n const maxAttempts = 10;\n\n while (currentElement && attempts < maxAttempts) {\n const computedStyle = window.getComputedStyle(currentElement);\n\n // Check if display is inline-flex\n if (computedStyle.display === \"inline-flex\") {\n return currentElement;\n }\n\n // Move to the next parent\n currentElement = currentElement.parentElement;\n attempts++;\n }\n\n return null;\n}\n\nexport function getFlexRemainingSpace(\n flexContainer: HTMLElement,\n ignoreElement: HTMLElement | ((e: HTMLElement) => boolean) = null\n) {\n const style = window.getComputedStyle(flexContainer);\n const isRow =\n style.flexDirection === \"row\" || style.flexDirection === \"row-reverse\";\n const containerSize = isRow\n ? flexContainer.offsetWidth\n : flexContainer.offsetHeight;\n const gap = parseFloat(style.gap) || 0;\n const paddingStart =\n parseFloat(isRow ? style.paddingLeft : style.paddingTop) || 0;\n const paddingEnd =\n parseFloat(isRow ? style.paddingRight : style.paddingBottom) || 0;\n\n let totalItemSize = 0;\n const items: HTMLElement[] = (\n [...flexContainer.children] as HTMLElement[]\n ).filter(\n (child) =>\n child instanceof HTMLElement &&\n (typeof ignoreElement === \"function\"\n ? !ignoreElement(child)\n : child !== ignoreElement)\n );\n for (let i = 0; i < items.length; i++) {\n const itemStyle = window.getComputedStyle(items[i]);\n const marginStart =\n parseFloat(isRow ? itemStyle.marginLeft : itemStyle.marginTop) || 0;\n const marginEnd =\n parseFloat(isRow ? itemStyle.marginRight : itemStyle.marginBottom) || 0;\n totalItemSize +=\n (isRow ? items[i].offsetWidth : items[i].offsetHeight) +\n marginStart +\n marginEnd;\n }\n\n // Add gaps (n-1 gaps for n items)\n totalItemSize += gap * (items.length - 1);\n\n // Calculate remaining space\n const remainingSpace =\n containerSize - totalItemSize - paddingStart - paddingEnd;\n return Math.max(0, remainingSpace);\n}\n\n// Cache for measurement results to optimize performance (only used with renderText)\nconst measurementCache = new Map<string, number>();\n\n/**\n * Measures text width with optional render function for styled content\n * @param container - The container element to clone styles from\n * @param renderText - Optional render function to apply styling to text before measurement\n */\nexport const measureText = (\n container: HTMLElement,\n renderText?: ((text: string) => React.ReactNode) | null\n) => {\n const span = document.createElement(\"span\");\n span.style.opacity = \"0\";\n span.style.position = \"absolute\";\n span.style.top = \"-1000px\";\n span.style.left = \"-1000px\";\n span.style.whiteSpace = \"nowrap\";\n span.style.pointerEvents = \"none\";\n\n const nodeRect = container.getBoundingClientRect();\n\n const containerClone = container.cloneNode(true) as HTMLElement;\n containerClone.style.maxWidth = `${nodeRect.width}px`;\n containerClone.style.position = \"absolute\";\n containerClone.style.pointerEvents = \"none\";\n containerClone.style.top = \"-99px\";\n containerClone.style.left = \"-99px\";\n containerClone.style.zIndex = \"-1\";\n\n container.parentElement?.appendChild(containerClone);\n containerClone.appendChild(span);\n\n return {\n measure: (text: string) => {\n // Only use cache when measuring styled content (renderText case)\n // This preserves original behavior for default case\n if (renderText) {\n const cacheKey = `${text}-styled`;\n\n // Check cache first\n if (measurementCache.has(cacheKey)) {\n return measurementCache.get(cacheKey)!;\n }\n\n // Clear previous content\n span.innerHTML = \"\";\n\n // Render the content using renderText\n const rendered = renderText(text);\n\n // Handle different types of rendered content\n if (typeof rendered === \"string\") {\n // Simple string - just set innerHTML\n span.innerHTML = rendered;\n } else if (React.isValidElement(rendered)) {\n // React element - use renderToStaticMarkup for synchronous rendering\n try {\n const html = renderToStaticMarkup(rendered);\n span.innerHTML = html;\n } catch (_e) {\n // Fallback to plain text if renderToStaticMarkup fails\n span.innerText = text;\n }\n } else {\n // Fallback to plain text\n span.innerText = text;\n }\n\n const width = span.clientWidth;\n\n // Cache the result\n measurementCache.set(cacheKey, width);\n\n // Limit cache size to prevent memory leaks\n if (measurementCache.size > 100) {\n const firstKey = measurementCache.keys().next().value;\n measurementCache.delete(firstKey);\n }\n\n return width;\n }\n\n // Original behavior when renderText is not provided\n span.innerText = text;\n return span.clientWidth;\n },\n destroy: () => {\n containerClone.removeChild(span);\n container.parentElement?.removeChild(containerClone);\n },\n };\n};\n\nexport const getMiddleTruncatedString = (\n text: string,\n ellipsis: string,\n container: HTMLElement,\n renderText?: ((text: string) => React.ReactNode) | null\n): string => {\n if (!text) return text;\n\n const { measure: getTextWidth, destroy: destroyMeasure } =\n measureText(container, renderText);\n\n const textWidth = getTextWidth(text);\n\n const containerWidthToCompare = container.clientWidth;\n\n const initialOffset = Math.floor(\n (containerWidthToCompare / textWidth) * text.length\n );\n\n if (textWidth <= containerWidthToCompare) {\n destroyMeasure();\n return text;\n }\n\n let offset = initialOffset;\n const attempts: Record<number, [number, string]> = {};\n const maxAttempts = 20;\n const buffer = 4;\n\n while (Object.values(attempts).length <= maxAttempts) {\n // If we have already tried this offset, stop\n if (attempts[offset]) break;\n\n // If we are at the beginning of the string, just return the ellipsis\n if (offset <= 1) {\n attempts[0] = [0, ellipsis];\n break;\n }\n\n const start = text\n .slice(0, Math.ceil((offset - ellipsis.length) / 2 - 1))\n .trimEnd();\n const end = text\n .slice(Math.floor((offset - ellipsis.length) / 2) - offset)\n .trimStart();\n const truncatedStr = start + ellipsis + end;\n const width = getTextWidth(truncatedStr);\n\n attempts[offset] = [width, truncatedStr];\n\n if (width >= containerWidthToCompare) {\n offset = offset - 2;\n } else {\n // If we are close to the container width, stop\n if (containerWidthToCompare - width < buffer) break;\n offset = offset + 2;\n }\n }\n\n // Remove the span element used for measuring text\n destroyMeasure();\n\n // Find the closest attempt that is smaller than the container width\n return (\n Object.values(attempts)\n .reverse()\n .find(([width]) => width < containerWidthToCompare)?.[1] ??\n Object.values(attempts)[0][1]\n );\n};\n\n// Utility functions for measurements\nexport const createMeasurementClone = (\n text: string,\n container: HTMLElement\n) => {\n const styles = window.getComputedStyle(container);\n const clone = document.createElement(\"span\");\n clone.style.visibility = \"hidden\";\n clone.style.position = \"absolute\";\n clone.style.width = `${container.clientWidth}px`;\n clone.style.fontSize = styles.fontSize;\n clone.style.fontFamily = styles.fontFamily;\n clone.style.lineHeight = styles.lineHeight;\n clone.textContent = text;\n document.body.appendChild(clone);\n return clone;\n};\n\nexport const checkIfTextTruncated = (\n text: string,\n container: HTMLElement,\n availableHeight?: number\n) => {\n // Use the new checkOverflow utility for consistency\n return checkOverflow(container, {\n type: \"vertical\",\n availableHeight,\n text,\n });\n};\n\nexport const calculateAvailableHeight = (container: HTMLElement) => {\n const parent = container.parentElement;\n if (!parent) return 0;\n\n const parentStyles = window.getComputedStyle(parent);\n const paddingTop = parseFloat(parentStyles.paddingTop) || 0;\n const paddingBottom = parseFloat(parentStyles.paddingBottom) || 0;\n const borderTopWidth = parseFloat(parentStyles.borderTopWidth) || 0;\n const borderBottomWidth = parseFloat(parentStyles.borderBottomWidth) || 0;\n\n return (\n parent.clientHeight -\n paddingTop -\n paddingBottom -\n borderTopWidth -\n borderBottomWidth\n );\n};\n\nexport const calculateAvailableWidth = (container: HTMLElement) => {\n const parent = container.parentElement;\n if (!parent) return 0;\n\n const parentStyles = window.getComputedStyle(parent);\n const paddingLeft = parseFloat(parentStyles.paddingLeft) || 0;\n const paddingRight = parseFloat(parentStyles.paddingRight) || 0;\n const borderLeftWidth = parseFloat(parentStyles.borderLeftWidth) || 0;\n const borderRightWidth = parseFloat(parentStyles.borderRightWidth) || 0;\n\n return (\n parent.clientWidth -\n paddingLeft -\n paddingRight -\n borderLeftWidth -\n borderRightWidth\n );\n};\n\n// Overflow detection utilities\nexport type OverflowType = \"horizontal\" | \"vertical\" | \"both\";\n\nexport interface OverflowCheckOptions {\n type?: OverflowType;\n availableHeight?: number;\n text?: string;\n}\n\nexport const checkHorizontalOverflow = (container: HTMLElement): boolean => {\n return container.scrollWidth > container.clientWidth;\n};\n\nexport const checkVerticalOverflow = (\n container: HTMLElement,\n availableHeight?: number\n): boolean => {\n const compareHeight = availableHeight ?? (container.clientHeight || container.offsetHeight);\n return container.scrollHeight > compareHeight;\n};\n\nexport const checkOverflow = (\n container: HTMLElement,\n options: OverflowCheckOptions = {}\n): boolean => {\n const { type = \"horizontal\", availableHeight, text } = options;\n\n // If text is provided, use measurement clone for more accurate detection\n if (text) {\n const clone = createMeasurementClone(text, container);\n let isOverflowing = false;\n\n switch (type) {\n case \"horizontal\":\n isOverflowing = clone.scrollWidth > container.clientWidth;\n break;\n case \"vertical\":\n isOverflowing = availableHeight\n ? clone.scrollHeight > availableHeight\n : clone.scrollHeight > (container.clientHeight || container.offsetHeight);\n break;\n case \"both\":\n isOverflowing =\n clone.scrollWidth > container.clientWidth ||\n (availableHeight\n ? clone.scrollHeight > availableHeight\n : clone.scrollHeight > (container.clientHeight || container.offsetHeight));\n break;\n }\n\n document.body.removeChild(clone);\n return isOverflowing;\n }\n\n // Use direct container measurements\n switch (type) {\n case \"horizontal\":\n return checkHorizontalOverflow(container);\n case \"vertical\":\n return checkVerticalOverflow(container, availableHeight);\n case \"both\":\n return checkHorizontalOverflow(container) || checkVerticalOverflow(container, availableHeight);\n default:\n return checkHorizontalOverflow(container);\n }\n};\n"],"names":["measurementCache","measureText","container","renderText","span","nodeRect","containerClone","text","cacheKey","rendered","React","html","renderToStaticMarkup","width","firstKey","getMiddleTruncatedString","ellipsis","getTextWidth","destroyMeasure","textWidth","containerWidthToCompare","initialOffset","offset","attempts","maxAttempts","buffer","start","end","truncatedStr","createMeasurementClone","styles","clone","calculateAvailableHeight","parent","parentStyles","paddingTop","paddingBottom","borderTopWidth","borderBottomWidth","checkHorizontalOverflow","checkVerticalOverflow","availableHeight","compareHeight","checkOverflow","options","type","isOverflowing"],"mappings":"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"}
1
+ {"version":3,"file":"helpers.js","sources":["../../../src/components/truncate/helpers.ts"],"sourcesContent":["import React from \"react\";\nimport { renderToStaticMarkup } from \"react-dom/server\";\n\n/**\n * Finds the closest parent element that has inline flex display\n * @param element - The starting HTMLElement\n * @returns The closest inline flex parent or null if not found\n */\nexport function findClosestInlineFlexParent(element: HTMLElement): HTMLElement | null {\n if (!element) return null;\n\n let currentElement = element.parentElement;\n let attempts = 0;\n const maxAttempts = 10;\n\n while (currentElement && attempts < maxAttempts) {\n const computedStyle = window.getComputedStyle(currentElement);\n\n // Check if display is inline-flex\n if (computedStyle.display === \"inline-flex\") {\n return currentElement;\n }\n\n // Move to the next parent\n currentElement = currentElement.parentElement;\n attempts++;\n }\n\n return null;\n}\n\nexport function getFlexRemainingSpace(\n flexContainer: HTMLElement,\n ignoreElement: HTMLElement | ((e: HTMLElement) => boolean) = null,\n) {\n const style = window.getComputedStyle(flexContainer);\n const isRow = style.flexDirection === \"row\" || style.flexDirection === \"row-reverse\";\n const containerSize = isRow ? flexContainer.offsetWidth : flexContainer.offsetHeight;\n const gap = parseFloat(style.gap) || 0;\n const paddingStart = parseFloat(isRow ? style.paddingLeft : style.paddingTop) || 0;\n const paddingEnd = parseFloat(isRow ? style.paddingRight : style.paddingBottom) || 0;\n\n let totalItemSize = 0;\n const items: HTMLElement[] = ([...flexContainer.children] as HTMLElement[]).filter(\n (child) =>\n child instanceof HTMLElement &&\n (typeof ignoreElement === \"function\" ? !ignoreElement(child) : child !== ignoreElement),\n );\n for (let i = 0; i < items.length; i++) {\n const itemStyle = window.getComputedStyle(items[i]);\n const marginStart = parseFloat(isRow ? itemStyle.marginLeft : itemStyle.marginTop) || 0;\n const marginEnd = parseFloat(isRow ? itemStyle.marginRight : itemStyle.marginBottom) || 0;\n totalItemSize +=\n (isRow ? items[i].offsetWidth : items[i].offsetHeight) + marginStart + marginEnd;\n }\n\n // Add gaps (n-1 gaps for n items)\n totalItemSize += gap * (items.length - 1);\n\n // Calculate remaining space\n const remainingSpace = containerSize - totalItemSize - paddingStart - paddingEnd;\n return Math.max(0, remainingSpace);\n}\n\n// ---------------------------------------------------------------------------\n// Canvas-based text measurement — no DOM mutations, no forced reflows.\n// A single CanvasRenderingContext2D is created once and reused for all\n// measurements across the lifetime of the page.\n// ---------------------------------------------------------------------------\n\nlet _cachedCanvasCtx: CanvasRenderingContext2D | null = null;\n\n/**\n * Returns the singleton canvas 2D context used for text measurement.\n * The canvas is created lazily on first call and reused thereafter.\n */\nfunction getCanvasCtx(): CanvasRenderingContext2D {\n if (!_cachedCanvasCtx) {\n const canvas = document.createElement(\"canvas\");\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) throw new Error(\"Failed to get 2d context from canvas\");\n _cachedCanvasCtx = ctx;\n }\n return _cachedCanvasCtx;\n}\n\n/**\n * Measures the rendered pixel width of a string using the canvas API.\n * This avoids any DOM layout or reflow cost.\n *\n * @param text - The string to measure.\n * @param font - A CSS font shorthand string (e.g. \"normal 400 14px Inter, sans-serif\").\n */\nfunction measureTextWidth(\n text: string,\n font: string,\n letterSpacing: string,\n wordSpacing: string,\n): number {\n const ctx = getCanvasCtx();\n ctx.font = font;\n ctx.letterSpacing = letterSpacing;\n ctx.wordSpacing = wordSpacing;\n return ctx.measureText(text).width;\n}\n\n/**\n * Builds a CSS font shorthand string from an element's computed style,\n * matching the font the browser will use to render text in that element.\n */\nfunction getComputedTextStyle(el: HTMLElement): {\n font: string;\n letterSpacing: string;\n wordSpacing: string;\n} {\n const cs = window.getComputedStyle(el);\n return {\n font: `${cs.fontStyle} ${cs.fontVariant} ${cs.fontWeight} ${cs.fontSize} ${cs.fontFamily}`,\n letterSpacing: cs.letterSpacing,\n wordSpacing: cs.wordSpacing,\n };\n}\n\nfunction createRenderedTextMeasurer(\n container: HTMLElement,\n renderText: (text: string) => React.ReactNode,\n) {\n const span = document.createElement(\"span\");\n span.style.opacity = \"0\";\n span.style.position = \"absolute\";\n span.style.top = \"-1000px\";\n span.style.left = \"-1000px\";\n span.style.whiteSpace = \"nowrap\";\n span.style.pointerEvents = \"none\";\n\n const nodeRect = container.getBoundingClientRect();\n const containerClone = container.cloneNode(true) as HTMLElement;\n containerClone.style.maxWidth = `${nodeRect.width}px`;\n containerClone.style.position = \"absolute\";\n containerClone.style.pointerEvents = \"none\";\n containerClone.style.top = \"-1000px\";\n containerClone.style.left = \"-1000px\";\n containerClone.style.zIndex = \"-1\";\n\n container.parentElement?.appendChild(containerClone);\n containerClone.appendChild(span);\n\n return {\n measure: (value: string) => {\n span.innerHTML = \"\";\n\n const rendered = renderText(value);\n if (typeof rendered === \"string\" || typeof rendered === \"number\") {\n span.textContent = String(rendered);\n } else if (React.isValidElement(rendered)) {\n try {\n span.innerHTML = renderToStaticMarkup(rendered);\n } catch (_error) {\n span.textContent = value;\n }\n } else {\n span.textContent = value;\n }\n\n return span.clientWidth;\n },\n destroy: () => {\n span.remove();\n containerClone.remove();\n },\n };\n}\n\nfunction getMiddleTruncatedStringWithMeasurer(\n text: string,\n ellipsis: string,\n containerW: number,\n measure: (value: string) => number,\n): string {\n if (measure(text) <= containerW) return text;\n\n const getCandidate = (charsToKeep: number) => {\n if (charsToKeep === 0) return ellipsis;\n\n const startLen = Math.floor(charsToKeep / 2);\n const endLen = Math.ceil(charsToKeep / 2);\n\n return (\n text.slice(0, startLen).trimEnd() + ellipsis + text.slice(text.length - endLen).trimStart()\n );\n };\n\n let lo = 0;\n let hi = text.length;\n\n while (lo < hi) {\n const mid = Math.ceil((lo + hi) / 2);\n const truncatedText = getCandidate(mid);\n\n if (measure(truncatedText) <= containerW) lo = mid;\n else hi = mid - 1;\n }\n\n return getCandidate(lo);\n}\n\n/**\n * Computes a middle-truncated version of `text` that fits within\n * `container.clientWidth` pixels.\n *\n * Uses a binary search over the total number of characters to keep.\n * Plain text uses canvas measurement; custom `renderText` falls back to DOM\n * measurement because styled markup can change the rendered width.\n *\n * @param text - The original string.\n * @param ellipsis - Separator to insert at the truncation point (e.g. \"…\").\n * @param container - The element whose `clientWidth` sets the budget and\n * whose computed font is used for measurement.\n * @param renderText - Optional custom renderer used for styled text measurement.\n * @returns The original string if it fits, or a middle-truncated string.\n */\nexport const getMiddleTruncatedString = (\n text: string,\n ellipsis: string,\n container: HTMLElement,\n renderText?: ((text: string) => React.ReactNode) | null,\n): string => {\n if (!text) return text;\n\n const { font, letterSpacing, wordSpacing } = getComputedTextStyle(container);\n const containerW = container.clientWidth;\n\n if (renderText) {\n const { measure, destroy } = createRenderedTextMeasurer(container, renderText);\n\n try {\n return getMiddleTruncatedStringWithMeasurer(text, ellipsis, containerW, measure);\n } finally {\n destroy();\n }\n }\n\n return getMiddleTruncatedStringWithMeasurer(text, ellipsis, containerW, (value) =>\n measureTextWidth(value, font, letterSpacing, wordSpacing),\n );\n};\n\n// Utility functions for measurements\nexport const createMeasurementClone = (text: string, container: HTMLElement) => {\n const styles = window.getComputedStyle(container);\n const clone = document.createElement(\"span\");\n clone.style.visibility = \"hidden\";\n clone.style.position = \"absolute\";\n clone.style.width = `${container.clientWidth}px`;\n clone.style.fontSize = styles.fontSize;\n clone.style.fontFamily = styles.fontFamily;\n clone.style.lineHeight = styles.lineHeight;\n clone.textContent = text;\n document.body.appendChild(clone);\n return clone;\n};\n\nexport const checkIfTextTruncated = (\n text: string,\n container: HTMLElement,\n availableHeight?: number,\n) => {\n // Use the new checkOverflow utility for consistency\n return checkOverflow(container, {\n type: \"vertical\",\n availableHeight,\n text,\n });\n};\n\nexport const calculateAvailableHeight = (container: HTMLElement) => {\n const parent = container.parentElement;\n if (!parent) return 0;\n\n const parentStyles = window.getComputedStyle(parent);\n const paddingTop = parseFloat(parentStyles.paddingTop) || 0;\n const paddingBottom = parseFloat(parentStyles.paddingBottom) || 0;\n const borderTopWidth = parseFloat(parentStyles.borderTopWidth) || 0;\n const borderBottomWidth = parseFloat(parentStyles.borderBottomWidth) || 0;\n\n return parent.clientHeight - paddingTop - paddingBottom - borderTopWidth - borderBottomWidth;\n};\n\nexport const calculateAvailableWidth = (container: HTMLElement) => {\n const parent = container.parentElement;\n if (!parent) return 0;\n\n const parentStyles = window.getComputedStyle(parent);\n const paddingLeft = parseFloat(parentStyles.paddingLeft) || 0;\n const paddingRight = parseFloat(parentStyles.paddingRight) || 0;\n const borderLeftWidth = parseFloat(parentStyles.borderLeftWidth) || 0;\n const borderRightWidth = parseFloat(parentStyles.borderRightWidth) || 0;\n\n return parent.clientWidth - paddingLeft - paddingRight - borderLeftWidth - borderRightWidth;\n};\n\n// Overflow detection utilities\nexport type OverflowType = \"horizontal\" | \"vertical\" | \"both\";\n\nexport interface OverflowCheckOptions {\n type?: OverflowType;\n availableHeight?: number;\n text?: string;\n}\n\nexport const checkHorizontalOverflow = (container: HTMLElement): boolean => {\n return container.scrollWidth > container.clientWidth;\n};\n\nexport const checkVerticalOverflow = (\n container: HTMLElement,\n availableHeight?: number,\n): boolean => {\n const compareHeight = availableHeight ?? (container.clientHeight || container.offsetHeight);\n return container.scrollHeight > compareHeight;\n};\n\nexport const checkOverflow = (\n container: HTMLElement,\n options: OverflowCheckOptions = {},\n): boolean => {\n const { type = \"horizontal\", availableHeight, text } = options;\n\n // If text is provided, use measurement clone for more accurate detection\n if (text) {\n const clone = createMeasurementClone(text, container);\n let isOverflowing = false;\n\n switch (type) {\n case \"horizontal\":\n isOverflowing = clone.scrollWidth > container.clientWidth;\n break;\n case \"vertical\":\n isOverflowing = availableHeight\n ? clone.scrollHeight > availableHeight\n : clone.scrollHeight > (container.clientHeight || container.offsetHeight);\n break;\n case \"both\":\n isOverflowing =\n clone.scrollWidth > container.clientWidth ||\n (availableHeight\n ? clone.scrollHeight > availableHeight\n : clone.scrollHeight > (container.clientHeight || container.offsetHeight));\n break;\n }\n\n document.body.removeChild(clone);\n return isOverflowing;\n }\n\n // Use direct container measurements\n switch (type) {\n case \"horizontal\":\n return checkHorizontalOverflow(container);\n case \"vertical\":\n return checkVerticalOverflow(container, availableHeight);\n case \"both\":\n return (\n checkHorizontalOverflow(container) || checkVerticalOverflow(container, availableHeight)\n );\n default:\n return checkHorizontalOverflow(container);\n }\n};\n"],"names":["_cachedCanvasCtx","getCanvasCtx","ctx","measureTextWidth","text","font","letterSpacing","wordSpacing","getComputedTextStyle","el","cs","createRenderedTextMeasurer","container","renderText","span","nodeRect","containerClone","value","rendered","React","renderToStaticMarkup","getMiddleTruncatedStringWithMeasurer","ellipsis","containerW","measure","getCandidate","charsToKeep","startLen","endLen","lo","hi","mid","truncatedText","getMiddleTruncatedString","destroy","createMeasurementClone","styles","clone","calculateAvailableHeight","parent","parentStyles","paddingTop","paddingBottom","borderTopWidth","borderBottomWidth","checkHorizontalOverflow","checkVerticalOverflow","availableHeight","compareHeight","checkOverflow","options","type","isOverflowing"],"mappings":"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"}