@jimka/typescript-ui 0.4.0 → 0.4.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.
- package/dist/lib/{AbstractBooleanInput-DSwKBAic.js → AbstractBooleanInput-DE5NNJT0.js} +2 -2
- package/dist/lib/{AbstractBooleanInput-DSwKBAic.js.map → AbstractBooleanInput-DE5NNJT0.js.map} +1 -1
- package/dist/lib/{AbstractInput-BmWGJTs1.js → AbstractInput-BxfrmD2W.js} +2 -2
- package/dist/lib/{AbstractInput-BmWGJTs1.js.map → AbstractInput-BxfrmD2W.js.map} +1 -1
- package/dist/lib/{AnchorConstraints-CVrMP9rz.js → AnchorConstraints-DdDYSDkf.js} +2 -2
- package/dist/lib/{AnchorConstraints-CVrMP9rz.js.map → AnchorConstraints-DdDYSDkf.js.map} +1 -1
- package/dist/lib/{AnimatedDropdown-DKas40B-.js → AnimatedDropdown-QLNasu_Y.js} +2 -2
- package/dist/lib/{AnimatedDropdown-DKas40B-.js.map → AnimatedDropdown-QLNasu_Y.js.map} +1 -1
- package/dist/lib/Border-CKKUk5G9.js +2 -0
- package/dist/lib/Border-CKKUk5G9.js.map +1 -0
- package/dist/lib/{Button-bjpWruNc.js → Button-MZDYJOMC.js} +2 -2
- package/dist/lib/{Button-bjpWruNc.js.map → Button-MZDYJOMC.js.map} +1 -1
- package/dist/lib/{Card-BdfbvOD_.js → Card-a4dzYrbX.js} +2 -2
- package/dist/lib/{Card-BdfbvOD_.js.map → Card-a4dzYrbX.js.map} +1 -1
- package/dist/lib/ComboBox-C04SfXAR.js +2 -0
- package/dist/lib/ComboBox-C04SfXAR.js.map +1 -0
- package/dist/lib/Component-fRQvgaEY.js +2 -0
- package/dist/lib/Component-fRQvgaEY.js.map +1 -0
- package/dist/lib/Container-0bsG2Q8Z.js +2 -0
- package/dist/lib/{Container-CAQpj4yb.js.map → Container-0bsG2Q8Z.js.map} +1 -1
- package/dist/lib/{DragManager-CHWCe3-8.js → DragManager-DRor_-1x.js} +2 -2
- package/dist/lib/{DragManager-CHWCe3-8.js.map → DragManager-DRor_-1x.js.map} +1 -1
- package/dist/lib/{FieldDecorator-CgAGcqCk.js → FieldDecorator-Bpx8J8n9.js} +2 -2
- package/dist/lib/{FieldDecorator-CgAGcqCk.js.map → FieldDecorator-Bpx8J8n9.js.map} +1 -1
- package/dist/lib/{Fit-DIYt2aQB.js → Fit-CL1m1nIZ.js} +2 -2
- package/dist/lib/{Fit-DIYt2aQB.js.map → Fit-CL1m1nIZ.js.map} +1 -1
- package/dist/lib/{Glyph-CeAIWyPB.js → Glyph-wN7bk7mg.js} +2 -2
- package/dist/lib/{Glyph-CeAIWyPB.js.map → Glyph-wN7bk7mg.js.map} +1 -1
- package/dist/lib/{Grid-ViA0joow.js → Grid-DHHmaB-Y.js} +2 -2
- package/dist/lib/{Grid-ViA0joow.js.map → Grid-DHHmaB-Y.js.map} +1 -1
- package/dist/lib/{GridConstraints-B1rxCw9B.js → GridConstraints-DVc1BmlP.js} +2 -2
- package/dist/lib/{GridConstraints-B1rxCw9B.js.map → GridConstraints-DVc1BmlP.js.map} +1 -1
- package/dist/lib/{Header-mKaqgfat.js → Header-2hKwQo_u.js} +2 -2
- package/dist/lib/{Header-mKaqgfat.js.map → Header-2hKwQo_u.js.map} +1 -1
- package/dist/lib/{IconText-BqwXA82-.js → IconText-DC7Xe34b.js} +2 -2
- package/dist/lib/{IconText-BqwXA82-.js.map → IconText-DC7Xe34b.js.map} +1 -1
- package/dist/lib/LayoutConstraints-LIHYYd2F.js +2 -0
- package/dist/lib/LayoutConstraints-LIHYYd2F.js.map +1 -0
- package/dist/lib/{LayoutSerialization-D82UtnDD.js → LayoutSerialization-D5bBas4W.js} +2 -2
- package/dist/lib/{LayoutSerialization-D82UtnDD.js.map → LayoutSerialization-D5bBas4W.js.map} +1 -1
- package/dist/lib/{LayoutSizes-DG9aW9k6.js → LayoutSizes-qNaURyiw.js} +2 -2
- package/dist/lib/LayoutSizes-qNaURyiw.js.map +1 -0
- package/dist/lib/{List-CUntS8ux.js → List-CG4NvwuV.js} +2 -2
- package/dist/lib/{List-CUntS8ux.js.map → List-CG4NvwuV.js.map} +1 -1
- package/dist/lib/Menu-CrZy2u0g.js +2 -0
- package/dist/lib/Menu-CrZy2u0g.js.map +1 -0
- package/dist/lib/MenuButton-wy_0RskC.js +2 -0
- package/dist/lib/MenuButton-wy_0RskC.js.map +1 -0
- package/dist/lib/{Panel-D2X33qR6.js → Panel-Rd9zkNXx.js} +2 -2
- package/dist/lib/{Panel-D2X33qR6.js.map → Panel-Rd9zkNXx.js.map} +1 -1
- package/dist/lib/{ProgressSpinner-DCyq02pd.js → ProgressSpinner-yt-VXyCb.js} +2 -2
- package/dist/lib/{ProgressSpinner-DCyq02pd.js.map → ProgressSpinner-yt-VXyCb.js.map} +1 -1
- package/dist/lib/{RadioButton-BJIAQkII.js → RadioButton-D23rId-V.js} +2 -2
- package/dist/lib/{RadioButton-BJIAQkII.js.map → RadioButton-D23rId-V.js.map} +1 -1
- package/dist/lib/{Scrollbar-CSFK-Y57.js → Scrollbar-SOj9psiP.js} +2 -2
- package/dist/lib/{Scrollbar-CSFK-Y57.js.map → Scrollbar-SOj9psiP.js.map} +1 -1
- package/dist/lib/{Slider-C-kQQYCj.js → Slider-DBnAZ-F7.js} +2 -2
- package/dist/lib/{Slider-C-kQQYCj.js.map → Slider-DBnAZ-F7.js.map} +1 -1
- package/dist/lib/{Spacer-D159iJy9.js → Spacer-qalSEJ5i.js} +2 -2
- package/dist/lib/{Spacer-D159iJy9.js.map → Spacer-qalSEJ5i.js.map} +1 -1
- package/dist/lib/{TabButton-CHkXBgCj.js → TabButton-DKECTTk1.js} +2 -2
- package/dist/lib/{TabButton-CHkXBgCj.js.map → TabButton-DKECTTk1.js.map} +1 -1
- package/dist/lib/{Text-D5pg7taZ.js → Text-KB5LksJl.js} +2 -2
- package/dist/lib/{Text-D5pg7taZ.js.map → Text-KB5LksJl.js.map} +1 -1
- package/dist/lib/{Tooltip-DzK6LxUt.js → Tooltip-Dro4DOZs.js} +2 -2
- package/dist/lib/{Tooltip-DzK6LxUt.js.map → Tooltip-Dro4DOZs.js.map} +1 -1
- package/dist/lib/{VBox-BNegDPs_.js → VBox-P3WFGkPc.js} +2 -2
- package/dist/lib/{VBox-BNegDPs_.js.map → VBox-P3WFGkPc.js.map} +1 -1
- package/dist/lib/{VirtualScroller-zQr-vKrO.js → VirtualScroller-Bv4KXGKW.js} +2 -2
- package/dist/lib/{VirtualScroller-zQr-vKrO.js.map → VirtualScroller-Bv4KXGKW.js.map} +1 -1
- package/dist/lib/component/button.es.js +1 -1
- package/dist/lib/component/button.es.js.map +1 -1
- package/dist/lib/component/chart.es.js +1 -1
- package/dist/lib/component/chart.es.js.map +1 -1
- package/dist/lib/component/container.es.js +1 -1
- package/dist/lib/component/container.es.js.map +1 -1
- package/dist/lib/component/diagram.es.js +1 -1
- package/dist/lib/component/display.es.js +1 -1
- package/dist/lib/component/editor.es.js +1 -1
- package/dist/lib/component/input.es.js +1 -1
- package/dist/lib/component/list.es.js +1 -1
- package/dist/lib/component/menubar.es.js +1 -1
- package/dist/lib/component/menubar.es.js.map +1 -1
- package/dist/lib/component/table.es.js +2 -2
- package/dist/lib/component/table.es.js.map +1 -1
- package/dist/lib/component/tree.es.js +1 -1
- package/dist/lib/core.es.js +1 -1
- package/dist/lib/layout.es.js +1 -1
- package/dist/lib/overlay.es.js +1 -1
- package/dist/lib/overlay.es.js.map +1 -1
- package/dist/lib/{selectionsEqual-4r5R7pTK.js → selectionsEqual-Ci3_uflt.js} +2 -2
- package/dist/lib/{selectionsEqual-4r5R7pTK.js.map → selectionsEqual-Ci3_uflt.js.map} +1 -1
- package/dist/lib/types/component/button/MenuButton.d.ts +1 -0
- package/dist/lib/types/component/button/SplitButton.d.ts +1 -0
- package/dist/lib/types/component/button/TabButton.d.ts +1 -0
- package/dist/lib/types/component/chart/ChartLegend.d.ts +0 -1
- package/dist/lib/types/component/container/CollapseButton.d.ts +0 -1
- package/dist/lib/types/component/container/TabPanel.d.ts +3 -0
- package/dist/lib/types/component/input/Link.d.ts +0 -1
- package/dist/lib/types/component/menubar/MenuBar.d.ts +1 -0
- package/dist/lib/types/component/menubar/MenuBarButton.d.ts +0 -1
- package/dist/lib/types/component/menubar/ToolBar.d.ts +1 -0
- package/dist/lib/types/component/table/Table.d.ts +1 -0
- package/dist/lib/types/core/BorderWidths.d.ts +12 -0
- package/dist/lib/types/core/Component.d.ts +1 -0
- package/dist/lib/types/core/Event.d.ts +2 -0
- package/dist/lib/types/layout/LayoutConstraints.d.ts +1 -0
- package/dist/lib/types/layout/LayoutSerialization.d.ts +3 -0
- package/dist/lib/types/overlay/Dock.d.ts +1 -0
- package/dist/lib/validation.es.js +1 -1
- package/package.json +1 -1
- package/dist/lib/Border-Bz29z-_7.js +0 -2
- package/dist/lib/Border-Bz29z-_7.js.map +0 -1
- package/dist/lib/ComboBox-CBw2VLLN.js +0 -2
- package/dist/lib/ComboBox-CBw2VLLN.js.map +0 -1
- package/dist/lib/Component-DHqrPwAw.js +0 -2
- package/dist/lib/Component-DHqrPwAw.js.map +0 -1
- package/dist/lib/Container-CAQpj4yb.js +0 -2
- package/dist/lib/LayoutConstraints-DkctJZXB.js +0 -2
- package/dist/lib/LayoutConstraints-DkctJZXB.js.map +0 -1
- package/dist/lib/LayoutSizes-DG9aW9k6.js.map +0 -1
- package/dist/lib/Menu-B_-SQj72.js +0 -2
- package/dist/lib/Menu-B_-SQj72.js.map +0 -1
- package/dist/lib/MenuButton-C79l8Ysf.js +0 -2
- package/dist/lib/MenuButton-C79l8Ysf.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Container-
|
|
1
|
+
{"version":3,"file":"Container-0bsG2Q8Z.js","names":[],"sources":["../../src/typescript/lib/core/Container.ts"],"sourcesContent":["// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { Component, ComponentOptions } from \"~/core/Component.js\";\nimport { callable } from \"~/core/Callable.js\";\n\n/**\n * Construction-time options for {@link Container}.\n *\n * Adds no fields over {@link ComponentOptions}; declared as a named extension\n * point so structural containers have a stable options type and so\n * {@link Panel}'s `PanelOptions` can extend it.\n *\n * @category Core\n */\nexport interface ContainerOptions extends ComponentOptions {}\n\n/**\n * A fit-parent {@link Component}: a container that fills the rect its parent's\n * layout manager allocates instead of shrinking to its content's size.\n *\n * `Component` already owns the container machinery — a layout manager, children,\n * insets, a child host. `Container`'s sole contribution is flipping the size\n * policy: it overrides `clampsToContentSize` to `false`, so its width and\n * height accept whatever the parent allocates and oversized content overflows\n * (clipped) rather than inflating the box back up to its content-derived\n * minimum. It keeps `Component`'s **zero** default insets and adds no scrolling.\n *\n * Use `Container` for structural regions that must fill their slot — a dock\n * `Split`/`Tab` region, an identity frame — without the perimeter padding or\n * native scrolling a content surface wants. For those, use\n * [`Panel`](/api/core/classes/Panel), which is a `Container` that adds a default\n * 4-pixel inset and an `autoScroll` stack on top.\n *\n * @category Core\n */\nclass Container<TOptions extends ContainerOptions = ContainerOptions> extends Component<TOptions> {\n\n /**\n * Overrides {@link Component.clampsToContentSize} to `false`: a container\n * fits whatever space its parent's layout manager allocates rather than\n * inflating up to its content-derived minimum. Oversized children clip (a\n * `Container` adds no scrolling — use [`Panel`](/api/core/classes/Panel) for\n * that). Only an explicit {@link Component.setMinSize} /\n * {@link Component.setMaxSize} remains a hard floor or ceiling.\n *\n * @returns `false`, so size clamping uses the container's own explicit\n * constraints only, not its content-derived ones.\n */\n protected clampsToContentSize(): boolean {\n return false;\n }\n}\n\nconst ContainerCallable = callable(Container);\ntype ContainerCallable<TOptions extends ContainerOptions = ContainerOptions> = Container<TOptions>;\nexport {\n Container as _Container,\n ContainerCallable as Container,\n};\n"],"mappings":"8CAmCA,IAAM,UAAN,cAA8E,CAAoB,CAa9F,qBAAyC,CACrC,MAAO,EACX,CACJ,EAEM,EAAoB,EAAS,SAAS"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{t as e}from"./DOM-67StIm5G.js";import{t}from"./Position-Ck_KD4cR.js";import{S as n,h as r,t as i}from"./Component-
|
|
2
|
-
//# sourceMappingURL=DragManager-
|
|
1
|
+
import{t as e}from"./DOM-67StIm5G.js";import{t}from"./Position-Ck_KD4cR.js";import{S as n,h as r,t as i}from"./Component-fRQvgaEY.js";import{a}from"./Tooltip-Dro4DOZs.js";import{t as o}from"./Text-KB5LksJl.js";var s=a.Band.Window-1,DragFeedback=class extends i{_valid=!0;constructor(){super(),this.setPosition(t.ABSOLUTE),this.setZIndex(s),this.setPointerEvents(`none`),this.applyTintForValidity()}isValid(){return this._valid}setValid(e){this._valid!==e&&(this._valid=e,this.applyTintForValidity())}attachTo(t,n){let r=this.getElement(!0);if(n&&n!==t){this.setX(t.getX()),this.setY(t.getY()),this.setWidth(t.getWidth()),this.setHeight(t.getHeight());let i=n.getElement(!0);e.source.getParentElement(r)!==i&&e.sink.appendChild(i,r);return}this.setX(0),this.setY(0),this.setWidth(t.getWidth()),this.setHeight(t.getHeight());let i=t.getElement(!0);e.source.getParentElement(r)!==i&&e.sink.appendChild(i,r)}detach(){this.removeElement()}applyTintForValidity(){let e=this._valid?`valid`:`invalid`;this.setBackgroundColor(`var(--ts-ui-drag-feedback-${e}-bg)`),this.setBorder({border:`2px solid var(--ts-ui-drag-feedback-${e}-border)`})}},c=r(DragFeedback),l=10200,u=160,d=28,f=6,DragGhost=class extends i{_label=null;constructor(e,n,r){super(),this.setPosition(t.FIXED),this.setZIndex(l),this.setPointerEvents(`none`),this.setWidth(n??u),this.setHeight(r??d),this.setBackgroundColor(`var(--ts-ui-drag-ghost-bg)`),this.setBorder({border:`1px solid var(--ts-ui-drag-ghost-border)`}),this.setShadow(`var(--ts-ui-drag-ghost-shadow)`),this.setBorderRadius(`var(--ts-ui-border-radius, 4px)`),this.setOpacity(.85),e!==void 0&&(this._label=new o(e),this._label.setPointerEvents(`none`),this.addComponent(this._label))}moveTo(e,t){this.setX(e),this.setY(t)}show(){let t=this.getElement(!0);this.scheduleLayout(),e.sink.appendChild(e.source.getDocumentElement(),t)}hide(){this.removeElement()}doLayout(){super.doLayout();let e=this.getContentBounds();return this._label&&e&&(this._label.setX(e.x+f),this._label.setY(e.y+f),this._label.setWidth(e.width-f*2),this._label.setHeight(e.height-f*2)),this}},p=r(DragGhost),m=a.Band.Window-1,h=2,g=1,ReorderIndicator=class extends i{constructor(){super(),this.setPosition(t.ABSOLUTE),this.setZIndex(m),this.setPointerEvents(`none`),this.setHeight(h),this.setBackgroundColor(`var(--ts-ui-drag-reorder-color)`)}setInsertionY(e){this.setY(e-g)}attachTo(t){let n=t.getElement(!0),r=this.getElement(!0);this.setX(0),this.setWidth(t.getWidth()),e.source.getParentElement(r)!==n&&e.sink.appendChild(n,r)}detach(){this.removeElement()}},_=r(ReorderIndicator),v=new Map,y=1e3,b=4,x=12,S=12,C=new Map,w=new Map,T=null,E;(function(e){function makeDragSource(e,t){return C.set(e.getId(),{component:e,options:t}),e.addMouseDownSubtreeListener(onSourceMouseDown),tearDownDragSource.bind(null,e)}e.makeDragSource=makeDragSource;function makeDropTarget(e,t){return w.set(e.getId(),{component:e,options:t}),tearDownDropTarget.bind(null,e)}e.makeDropTarget=makeDropTarget;function isDragging(){return T!==null&&T.committed}e.isDragging=isDragging;function cancel(){T!==null&&endSession(!1,0,0)}e.cancel=cancel})(E||={});function resolveDragData(e){return typeof e.dragData==`function`?e.dragData():e.dragData}function tearDownDragSource(e){e.removeMouseDownSubtreeListener(onSourceMouseDown),C.delete(e.getId())}function tearDownDropTarget(e){w.delete(e.getId())}function onSourceMouseDown(t){if(T!==null||t.button!==0)return;let r=C.get(this.getId());if(!r)return;let i=r.component,a=r.options;T={source:i,sourceOptions:a,dragData:resolveDragData(a),startX:t.clientX,startY:t.clientY,committed:!1,ghost:null,feedback:null,indicator:null,currentTarget:null,previousBodyCursor:e.source.getInlineStyle(e.source.getBody(),`cursor`)},n.addViewportListener(i,`mousemove`,onMouseMove),n.addViewportListener(i,`mouseup`,onMouseUp)}function commitSession(t){t.committed=!0;let n=t.sourceOptions.ghostFactory?t.sourceOptions.ghostFactory(t.source,t.dragData):new p;if(t.ghost=n,t.feedback=new c,t.indicator=new _,typeof n.show==`function`)n.show();else{let t=n.getElement(!0);e.sink.appendChild(e.source.getDocumentElement(),t)}t.sourceOptions.cursor&&e.sink.apply(e.source.getBody(),{style:{cursor:t.sourceOptions.cursor}})}function buildDetail(e,t,n){return{dragData:e.dragData,sourceId:e.source.getId(),clientX:t,clientY:n}}function pickDropTarget(t,n){let r=e.source.elementsFromPoint(t,n);for(let t of r){let n=w.get(e.source.getId(t));if(n)return n}return null}function leaveCurrentTarget(e,t){if(e.currentTarget===null)return;let n=w.get(e.currentTarget.getId());n&&n.options.onDragLeave&&n.options.onDragLeave(t),e.feedback&&e.feedback.detach(),e.indicator&&e.indicator.detach(),e.currentTarget=null}function enterNewTarget(e,t,n){let r=t.options.accepts(n);if(e.feedback&&!t.options.suppressValidityTint&&(e.feedback.setValid(r),e.feedback.attachTo(t.component,t.options.feedbackHost)),!r){e.currentTarget=t.component;return}let i=t.options.onDragOver?.(n);typeof i==`number`&&e.indicator?(e.indicator.attachTo(t.component),e.indicator.setInsertionY(i)):e.indicator&&e.indicator.detach(),e.currentTarget=t.component}function onMouseMove(e){if(T===null)return;let t=T;if(!t.committed){let r=e.clientX-t.startX,i=e.clientY-t.startY;if(r*r+i*i<b*b)return!0;let a=buildDetail(t,e.clientX,e.clientY);if(t.sourceOptions.onDragStart?.(a)===!1)return endSession(!1,e.clientX,e.clientY),!0;commitSession(t),n.fireEvent(t.source,`dragstart`,{detail:a})}if(t.ghost){let n=t.ghost;typeof n.moveTo==`function`?n.moveTo(e.clientX+x,e.clientY+S):(t.ghost.setX(e.clientX+x),t.ghost.setY(e.clientY+S))}let r=buildDetail(t,e.clientX,e.clientY),i=pickDropTarget(e.clientX,e.clientY);if(i===null)return leaveCurrentTarget(t,r),!0;if(t.currentTarget!==i.component)return leaveCurrentTarget(t,r),enterNewTarget(t,i,r),!0;let a=i.options.accepts(r);if(t.feedback&&!i.options.suppressValidityTint&&t.feedback.setValid(a),!a)return t.indicator&&t.indicator.detach(),!0;let o=i.options.onDragOver?.(r);return typeof o==`number`&&t.indicator?(t.indicator.attachTo(i.component),t.indicator.setInsertionY(o)):t.indicator&&t.indicator.detach(),!0}function onMouseUp(e){if(T===null)return;let t=T,r=buildDetail(t,e.clientX,e.clientY),i=!1;if(t.committed&&t.currentTarget!==null){let e=w.get(t.currentTarget.getId());e&&(e.options.accepts(r)&&e.options.onDrop?.(r)!==!1&&n.fireEvent(t.source,`drop`,{detail:r}),i=!0)}return endSession(i,e.clientX,e.clientY),!0}function endSession(t,r,i){if(T===null)return;let a=T;if(n.removeViewportListener(a.source,`mousemove`,onMouseMove),n.removeViewportListener(a.source,`mouseup`,onMouseUp),a.feedback&&a.feedback.dispose(),a.indicator&&a.indicator.dispose(),a.ghost)if(a.sourceOptions.ghostFactory){let e=a.ghost;typeof e.hide==`function`?e.hide():a.ghost.removeElement()}else a.ghost.dispose();if(a.sourceOptions.cursor&&e.sink.apply(e.source.getBody(),{style:{cursor:a.previousBodyCursor}}),a.committed){let e=buildDetail(a,r,i);n.fireEvent(a.source,`dragend`,{detail:e}),a.sourceOptions.onDragEnd?.(e,t)}T=null}export{p as a,_ as i,y as n,c as o,v as r,E as t};
|
|
2
|
+
//# sourceMappingURL=DragManager-DRor_-1x.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DragManager-CHWCe3-8.js","names":[],"sources":["../../src/typescript/lib/overlay/DragFeedback.ts","../../src/typescript/lib/overlay/DragGhost.ts","../../src/typescript/lib/overlay/ReorderIndicator.ts","../../src/typescript/lib/overlay/DragManager.ts"],"sourcesContent":["// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { Component } from \"~/core/Component.js\";\nimport { Position } from \"~/primitive/Position.js\";\nimport { callable } from \"~/core/Callable.js\";\nimport { LayerManager } from \"~/core/LayerManager.js\";\nimport { DOM } from \"~/core/DOM.js\";\n\n/**\n * Z-order for the drop-target validity tint. The tint highlights a drop target,\n * which lives in ordinary app content — so it must sit **below** the lowest\n * {@link LayerManager} band (the {@link Window} band) or it paints over a\n * floating window, while still sitting above the target's own content (app\n * z-indexes top out near 3). The app tree establishes no isolating stacking\n * context, so a higher value escapes to the root context and beats windows —\n * which is exactly the bug `Band.Window - 1` avoids. Shared rationale with\n * {@link ReorderIndicator}; the drag ghost sits above both at the root.\n */\nconst Z_INDEX = LayerManager.Band.Window - 1;\n\n/**\n * A validity tint overlay drawn on top of the row currently being hovered\n * during an active drag. The colour swaps between the `valid` and\n * `invalid` theme tokens via {@link setValid}; the geometry is mirrored\n * onto a drop target via {@link attachTo}.\n *\n * Owned by [`DragManager`](/api/overlay/variables/DragManager) — application\n * code does not instantiate this directly.\n *\n * @category Core\n */\nclass DragFeedback extends Component {\n\n private _valid: boolean = true;\n\n /**\n * Constructs a drag-feedback overlay. The overlay is not attached\n * until {@link attachTo} is called.\n */\n constructor() {\n super();\n\n this.setPosition(Position.ABSOLUTE);\n this.setZIndex(Z_INDEX);\n this.setPointerEvents(\"none\");\n\n this.applyTintForValidity();\n }\n\n /**\n * Returns whether the overlay is currently showing the \"valid drop\"\n * tint.\n *\n * @returns `true` for the valid tint, `false` for the invalid tint.\n */\n isValid(): boolean {\n return this._valid;\n }\n\n /**\n * Switches the overlay between the `valid` and `invalid` theme\n * tokens. Idempotent — repeated calls with the same value are a\n * no-op.\n *\n * @param valid - `true` to show the valid tint, `false` for invalid.\n */\n setValid(valid: boolean): void {\n if (this._valid === valid) {\n return;\n }\n\n this._valid = valid;\n\n this.applyTintForValidity();\n }\n\n /**\n * Sizes this overlay to cover the drop target and appends it to the DOM.\n *\n * With no `host`, the tint is a child of the target, covering its body. When\n * a `host` is given, the tint instead lives in that (non-scrolling) layer,\n * sized to the target's box within it — so a target that scrolls its own\n * content (a Tab strip's clip frame) gets a tint over the *viewport* that\n * stays put instead of riding the scroll.\n *\n * @param target - The drop target whose box the tint should cover.\n * @param host - Optional non-scrolling layer to host the tint (see\n * {@link DropTargetOptions.feedbackHost}). Defaults to the target.\n */\n attachTo(target: Component, host?: Component): void {\n const myEl = this.getElement(true)!;\n\n if (host && host !== target) {\n // Overlay the target's box from within the host layer.\n this.setX(target.getX());\n this.setY(target.getY());\n this.setWidth(target.getWidth());\n this.setHeight(target.getHeight());\n\n const hostEl = host.getElement(true)!;\n if (DOM.source.getParentElement(myEl) !== hostEl) {\n DOM.sink.appendChild(hostEl, myEl);\n }\n\n return;\n }\n\n // Cover the target's own body as a child of it.\n this.setX(0);\n this.setY(0);\n this.setWidth(target.getWidth());\n this.setHeight(target.getHeight());\n\n const targetEl = target.getElement(true)!;\n if (DOM.source.getParentElement(myEl) !== targetEl) {\n DOM.sink.appendChild(targetEl, myEl);\n }\n }\n\n /**\n * Removes the overlay element from the DOM.\n */\n detach(): void {\n this.removeElement();\n }\n\n /**\n * Writes the background and border CSS variables that correspond to\n * the cached validity state. Called from the constructor and from\n * {@link setValid} on transitions.\n */\n private applyTintForValidity(): void {\n const suffix = this._valid ? \"valid\" : \"invalid\";\n\n this.setBackgroundColor(`var(--ts-ui-drag-feedback-${suffix}-bg)`);\n this.setBorder({ border: `2px solid var(--ts-ui-drag-feedback-${suffix}-border)` });\n }\n}\n\nconst DragFeedbackCallable = callable(DragFeedback);\ntype DragFeedbackCallable = DragFeedback;\nexport {\n DragFeedback as _DragFeedback,\n DragFeedbackCallable as DragFeedback,\n};\n","// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { Component } from \"~/core/Component.js\";\nimport { Position } from \"~/primitive/Position.js\";\nimport { Text } from \"~/component/input/Text.js\";\nimport { callable } from \"~/core/Callable.js\";\nimport { DOM } from \"~/core/DOM.js\";\n\n/**\n * Z-order ceiling for the drag ghost. The follow-the-cursor preview rides above\n * everything during a drag — appended at the document root, above the\n * LayerManager bands — so it is never occluded by a floating window or by the\n * per-target highlights ([`DragFeedback`](/api/overlay/classes/DragFeedback) /\n * [`ReorderIndicator`](/api/overlay/classes/ReorderIndicator)), which deliberately\n * sit *below* the window band instead.\n */\nconst Z_INDEX = 10200;\n\n/**\n * Default ghost width when the caller omits an explicit size. Picked to\n * comfortably surround a one-line label without measuring text.\n */\nconst DEFAULT_WIDTH = 160;\n\n/** Default ghost height — one row's worth of vertical room. */\nconst DEFAULT_HEIGHT = 28;\n\n/**\n * Inner padding around the optional ghost label so text doesn't crowd the\n * border at the framework's default font size.\n */\nconst LABEL_INSET = 6;\n\n/**\n * A floating drag preview that follows the pointer during an active drag\n * session, drawn above every other overlay. Created and owned by\n * [`DragManager`](/api/overlay/variables/DragManager); application code does\n * not instantiate this directly.\n *\n * The ghost is `Position.FIXED` (one of the documented overlay carve-outs\n * in `ARCHITECTURE.md` §Positioning) and renders with\n * `pointer-events: none` so the manager's\n * `document.elementsFromPoint` hit-test always returns the row underneath.\n *\n * @category Core\n */\nclass DragGhost extends Component {\n\n private _label: Text | null = null;\n\n /**\n * Constructs a drag ghost. The caller positions it via\n * {@link moveTo} and toggles visibility through {@link show} /\n * {@link hide}.\n *\n * @param label - Optional text drawn inside the ghost.\n * @param width - Optional width in pixels (defaults to 160).\n * @param height - Optional height in pixels (defaults to 28).\n */\n constructor(label?: string, width?: number, height?: number) {\n super();\n\n this.setPosition(Position.FIXED);\n this.setZIndex(Z_INDEX);\n this.setPointerEvents(\"none\");\n this.setWidth(width ?? DEFAULT_WIDTH);\n this.setHeight(height ?? DEFAULT_HEIGHT);\n\n this.setBackgroundColor(\"var(--ts-ui-drag-ghost-bg)\");\n this.setBorder({ border: \"1px solid var(--ts-ui-drag-ghost-border)\" });\n this.setShadow(\"var(--ts-ui-drag-ghost-shadow)\");\n this.setBorderRadius(\"var(--ts-ui-border-radius, 4px)\");\n this.setOpacity(Number(\"0.85\"));\n\n if (label !== undefined) {\n this._label = new Text(label);\n this._label.setPointerEvents(\"none\");\n this.addComponent(this._label);\n }\n }\n\n /**\n * Repositions the ghost so its top-left corner sits at\n * `(clientX, clientY)`. `DragManager` calls this on every `mousemove`\n * during an active drag.\n *\n * @param clientX - The viewport X (already offset from the cursor by the manager).\n * @param clientY - The viewport Y (already offset from the cursor by the manager).\n */\n moveTo(clientX: number, clientY: number): void {\n this.setX(clientX);\n this.setY(clientY);\n }\n\n /**\n * Appends the ghost to `<html>` and schedules a layout pass. Used by\n * `DragManager` when a drag commits past the movement threshold.\n */\n show(): void {\n const el = this.getElement(true)!;\n\n this.scheduleLayout();\n DOM.sink.appendChild(DOM.source.getDocumentElement(), el);\n }\n\n /**\n * Removes the ghost element from the DOM. Used by `DragManager` on\n * mouseup / cancel.\n */\n hide(): void {\n this.removeElement();\n }\n\n /**\n * Lays out the optional label inside the ghost's content box.\n *\n * @returns This component, for method chaining.\n */\n doLayout(): this {\n super.doLayout();\n\n const box = this.getContentBounds();\n\n if (this._label && box) {\n this._label.setX(box.x + LABEL_INSET);\n this._label.setY(box.y + LABEL_INSET);\n this._label.setWidth(box.width - LABEL_INSET * 2);\n this._label.setHeight(box.height - LABEL_INSET * 2);\n }\n\n return this;\n }\n}\n\nconst DragGhostCallable = callable(DragGhost);\ntype DragGhostCallable = DragGhost;\nexport {\n DragGhost as _DragGhost,\n DragGhostCallable as DragGhost,\n};\n","// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { Component } from \"~/core/Component.js\";\nimport { Position } from \"~/primitive/Position.js\";\nimport { callable } from \"~/core/Callable.js\";\nimport { LayerManager } from \"~/core/LayerManager.js\";\nimport { DOM } from \"~/core/DOM.js\";\n\n/**\n * Z-order shared with {@link DragFeedback}: just **below** the lowest\n * {@link LayerManager} band (the {@link Window} band) so this drop-target\n * insertion line — drawn over app content that establishes no isolating\n * stacking context — never paints over a floating window, while still sitting\n * above the target's own content. The drag ghost sits above both at the root.\n */\nconst Z_INDEX = LayerManager.Band.Window - 1;\n\n/** Height of the insertion-line bar in pixels. */\nconst BAR_HEIGHT = 2;\n\n/**\n * Half the bar height — subtracted in {@link ReorderIndicator.setInsertionY}\n * so the 2 px bar is centred on the insertion line.\n */\nconst BAR_HALF = 1;\n\n/**\n * A 2 px horizontal bar drawn between rows to mark the insertion line\n * during an active drag-reorder gesture.\n *\n * Reserved for future sibling-reorder work — drop-on-directory does not\n * use this overlay. The class ships now so the public API surface and\n * theme tokens stabilise alongside\n * [`DragGhost`](/api/overlay/classes/DragGhost) and\n * [`DragFeedback`](/api/overlay/classes/DragFeedback); the row-DnD wiring\n * in [`TreeTable`](/api/component/table/classes/TreeTable) only attaches\n * the feedback tint.\n *\n * @category Core\n */\nclass ReorderIndicator extends Component {\n\n /**\n * Constructs a reorder indicator. The bar is not attached until\n * {@link attachTo} is called.\n */\n constructor() {\n super();\n\n this.setPosition(Position.ABSOLUTE);\n this.setZIndex(Z_INDEX);\n this.setPointerEvents(\"none\");\n this.setHeight(BAR_HEIGHT);\n\n this.setBackgroundColor(\"var(--ts-ui-drag-reorder-color)\");\n }\n\n /**\n * Centres the bar on the given y-coordinate within the attached\n * target. The `- BAR_HALF` shift accounts for the 2 px bar height.\n *\n * @param y - Insertion-line y, measured from the target's top edge.\n */\n setInsertionY(y: number): void {\n this.setY(y - BAR_HALF);\n }\n\n /**\n * Mirrors the target's width onto the bar and appends the bar\n * element to the target.\n *\n * @param target - The drop target whose top-left coordinate space\n * the bar is positioned within.\n */\n attachTo(target: Component): void {\n const targetEl = target.getElement(true)!;\n const myEl = this.getElement(true)!;\n\n this.setX(0);\n this.setWidth(target.getWidth());\n\n if (DOM.source.getParentElement(myEl) === targetEl) {\n return;\n }\n\n DOM.sink.appendChild(targetEl, myEl);\n }\n\n /**\n * Removes the bar element from the DOM.\n */\n detach(): void {\n this.removeElement();\n }\n}\n\nconst ReorderIndicatorCallable = callable(ReorderIndicator);\ntype ReorderIndicatorCallable = ReorderIndicator;\nexport {\n ReorderIndicator as _ReorderIndicator,\n ReorderIndicatorCallable as ReorderIndicator,\n};\n","// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { Component } from \"~/core/Component.js\";\nimport { DragFeedback } from \"~/overlay/DragFeedback.js\";\nimport { DragGhost } from \"~/overlay/DragGhost.js\";\nimport { Event } from \"~/core/Event.js\";\nimport { ReorderIndicator } from \"~/overlay/ReorderIndicator.js\";\nimport { DOM } from \"~/core/DOM.js\";\n\n/**\n * Arbitrary, caller-defined payload attached to a drag source — the\n * shape is consumer-domain and the manager never inspects fields.\n *\n * @category Core\n */\nexport type DragData = Record<string, unknown>;\n\n/**\n * Payload delivered to every named drag-source / drop-target callback\n * and to every fired DOM event. Field names are stable across\n * `dragstart`, `dragover`, `dragleave`, `drop`, `dragend`.\n *\n * @category Core\n */\nexport interface DragEventDetail {\n /** The source's resolved drag data — read from the source options at session start. */\n dragData : DragData;\n /** The source component's id (`getId()`), useful for cycle / self-drop checks. */\n sourceId : string;\n /** Viewport-relative pointer X at the moment the event was raised. */\n clientX : number;\n /** Viewport-relative pointer Y at the moment the event was raised. */\n clientY : number;\n}\n\n/**\n * Drag-data payload attached to every tab-header drag — the cross-container\n * contract shared by the within-strip reorder path, tab tear-off / re-dock, the\n * Ctrl-drag window re-dock, and the downstream edge-split / dock-manager work.\n * A drop target reads it off {@link DragEventDetail}'s `dragData`. Because\n * {@link DragData} is a plain record it cannot carry a live component reference,\n * so `componentId` keys into the module-level `tabDragRegistry` to resolve the\n * dragged content.\n *\n * @category Core\n */\nexport interface TabDragData {\n /** Discriminator a drop target tests in its `accepts` predicate. */\n tabDrag: true;\n /** The source strip's stable id — distinguishes reorder-within from dock-from-elsewhere. */\n sourceTabId: string;\n /** The dragged content component's id — the key into `tabDragRegistry`. */\n componentId: string;\n /** The tab label — used for the drag ghost and the tear-off window title. */\n label: string;\n}\n\n/**\n * Resolves a {@link TabDragData} `componentId` back to the live content\n * component being dragged. Written when a header drag starts and cleared when it\n * ends, so a drop target — the same strip, another strip, or a torn-off\n * {@link DragData}-carrying window — can move the real component rather than\n * only learning its id. Shared by-import across `Tab` and `Window`; one\n * instance, so a source-side write is visible to the destination-side read.\n */\nexport const tabDragRegistry: Map<string, Component> = new Map<string, Component>();\n\n/**\n * Dwell, in milliseconds, before a tab held over a drop target spring-loads a\n * raise of that target's host window — surfacing a backgrounded float so the user\n * can aim the drop. Shared by the two dock drop surfaces so a region body\n * ([`DockRegion`](/api/layout/classes/DockRegion)) and a tab bar\n * ([`TabBar`](/api/component/container/classes/TabBar)) raise on the same cadence.\n *\n * Long enough that brushing a drag across a background window in transit does not\n * raise it, short enough that a deliberate hover surfaces the target. Set above a\n * `MenuItem` submenu's 150ms hover delay because raising a whole window is a\n * heavier, more disruptive action than opening a submenu, so it should demand a\n * clearly deliberate pause.\n */\nexport const SPRING_RAISE_DELAY_MS = 1000;\n\n/**\n * Construction-time options accepted by {@link DragManager.makeDragSource}.\n *\n * @category Core\n */\nexport interface DragSourceOptions {\n /** Static or factory-produced payload attached to the session. */\n dragData : DragData | (() => DragData);\n /**\n * Optional veto callback fired the moment the threshold is crossed.\n * Return `false` to abort the drag before any overlay is shown.\n */\n onDragStart? : (detail: DragEventDetail) => boolean | void;\n /**\n * Optional ghost factory. The returned component is used in place of\n * the manager's default ghost (which carries no label and matches the\n * source's size). The component must be detached when returned.\n */\n ghostFactory?: (source: Component, data: DragData) => Component;\n /** CSS cursor applied to `<body>` while the drag is active. */\n cursor? : string;\n /**\n * Fired once the gesture ends, after any `onDrop`. `dropped` is `true` when\n * the release was handled by a registered drop target — whether the target\n * accepted the drop or refused it — and `false` only on a release over empty\n * space. Lets a source distinguish a release that landed on a target from a\n * fall-through to empty space (e.g. tab tear-off), the signal the `\"dragend\"`\n * DOM event alone cannot carry.\n */\n onDragEnd? : (detail: DragEventDetail, dropped: boolean) => void;\n}\n\n/**\n * Construction-time options accepted by {@link DragManager.makeDropTarget}.\n *\n * @category Core\n */\nexport interface DropTargetOptions {\n /**\n * Validity predicate. Returns `true` when the dragged source may\n * drop on this target; the visual feedback tint mirrors the result.\n */\n accepts : (detail: DragEventDetail) => boolean;\n /**\n * Optional hover callback. Return a number to position the\n * [`ReorderIndicator`](/api/overlay/classes/ReorderIndicator) at the\n * given y inside the target; return `null` / `undefined` for no\n * reorder line.\n */\n onDragOver? : (detail: DragEventDetail) => number | null | void;\n /** Optional leave callback (cursor exits target's box). */\n onDragLeave? : (detail: DragEventDetail) => void;\n /** Optional drop callback — return `false` to suppress the `drop` event. */\n onDrop? : (detail: DragEventDetail) => boolean | void;\n /**\n * Suppresses the whole-target validity tint\n * ([`DragFeedback`](/api/overlay/classes/DragFeedback)) for this target. Pass it\n * when the target paints its own positional validity feedback (e.g. a\n * [`DockRegion`](/api/layout/classes/DockRegion) colours the drop *zone*\n * blue/red in `onDragOver`) so the two don't stack into a tinted frame *and*\n * a tinted zone. `accepts` still governs whether `onDragOver`/`onDrop` fire.\n */\n suppressValidityTint?: boolean;\n /**\n * Optional non-scrolling layer to host the validity tint, sized to the\n * target's box within it. Pass it when the target scrolls its own content\n * (e.g. a Tab strip's clip frame) so the tint overlays the *viewport* and\n * stays put instead of riding the scroll. Defaults to the target itself.\n */\n feedbackHost?: Component;\n}\n\ninterface DragSourceRecord {\n component: Component;\n options: DragSourceOptions;\n}\n\ninterface DropTargetRecord {\n component: Component;\n options: DropTargetOptions;\n}\n\ninterface DragSession {\n source: Component;\n sourceOptions: DragSourceOptions;\n dragData: DragData;\n startX: number;\n startY: number;\n committed: boolean;\n ghost: Component | null;\n feedback: DragFeedback | null;\n indicator: ReorderIndicator | null;\n currentTarget: Component | null;\n previousBodyCursor: string;\n}\n\n/**\n * Distance the cursor must travel between `mousedown` and `mousemove`\n * before the press-and-drag commits to a drag. The 4 px slop matches\n * the standard HIG threshold on Windows and macOS — anything shorter\n * fires a drag on plain clicks; anything longer feels unresponsive.\n */\nconst DRAG_THRESHOLD = 4;\n\n/**\n * Diagonal offsets applied to the ghost's top-left corner so the cursor\n * stays clear of the preview. Matches Finder / VS Code placement.\n */\nconst GHOST_OFFSET_X = 12;\nconst GHOST_OFFSET_Y = 12;\n\nconst dragSources = new Map<string, DragSourceRecord>();\nconst dropTargets = new Map<string, DropTargetRecord>();\nlet activeSession: DragSession | null = null;\n\n/**\n * Process-wide drag-and-drop coordinator. Maintains the global source /\n * target registry, owns the single active drag session, and\n * positions the three overlay components\n * ([`DragGhost`](/api/overlay/classes/DragGhost),\n * [`DragFeedback`](/api/overlay/classes/DragFeedback),\n * [`ReorderIndicator`](/api/overlay/classes/ReorderIndicator)) above the\n * page during a drag.\n *\n * Consumers register through the two factory functions and receive a\n * teardown closure to unwire when the source / target component goes\n * away. The manager itself fires no events directly — every callback\n * lives on the option bag the caller passed to the factory.\n *\n * @example\n * ```typescript\n * const tearDownSrc = DragManager.makeDragSource(row, {\n * dragData: () => ({ recordId: row.getRecord()?.get('id') }),\n * });\n * const tearDownTgt = DragManager.makeDropTarget(folder, {\n * accepts: (d) => d.dragData.recordId !== folder.getRecord()?.get('id'),\n * onDrop: (d) => moveRecord(d.dragData.recordId, folder),\n * });\n * ```\n *\n * @category Core\n */\nexport namespace DragManager {\n\n /**\n * Registers a component as a drag source. The component's mousedown\n * event begins a pending drag session that commits once the cursor\n * travels past the 4 px movement threshold.\n *\n * @param component - The source component.\n * @param options - Drag source configuration.\n *\n * @returns A teardown function that removes the source registration\n * and the mousedown listener.\n */\n export function makeDragSource(component: Component, options: DragSourceOptions): () => void {\n dragSources.set(component.getId(), { component, options });\n component.addMouseDownSubtreeListener(onSourceMouseDown);\n\n return tearDownDragSource.bind(null, component);\n }\n\n /**\n * Registers a component as a drop target. The component is queried\n * for `accepts` during every `mousemove` while a drag is active and\n * receives the configured callbacks at the appropriate phases.\n *\n * @param component - The drop target.\n * @param options - Drop target configuration.\n *\n * @returns A teardown function that removes the target registration.\n */\n export function makeDropTarget(component: Component, options: DropTargetOptions): () => void {\n dropTargets.set(component.getId(), { component, options });\n\n return tearDownDropTarget.bind(null, component);\n }\n\n /**\n * Returns whether a drag is currently in progress (committed past\n * the 4 px movement threshold).\n *\n * @returns `true` while the ghost is visible; `false` otherwise.\n */\n export function isDragging(): boolean {\n return activeSession !== null && activeSession.committed;\n }\n\n /**\n * Aborts an in-flight drag. Mirrors a `mouseup` outside any drop\n * target — no drop callback fires; the session tears down.\n */\n export function cancel(): void {\n if (activeSession === null) {\n return;\n }\n\n endSession(false, 0, 0);\n }\n}\n\n/**\n * Resolves the source's drag-data payload — accepts either a literal or\n * a factory function on every drag start so callers can carry per-row\n * state without re-registering the source.\n */\nfunction resolveDragData(options: DragSourceOptions): DragData {\n return typeof options.dragData === \"function\" ? options.dragData() : options.dragData;\n}\n\n/**\n * Removes the per-component mousedown listener and drops the source\n * record. Bound to `(component)` by `makeDragSource` so the returned\n * teardown closure stays a stable named-function reference.\n */\nfunction tearDownDragSource(component: Component): void {\n component.removeMouseDownSubtreeListener(onSourceMouseDown);\n dragSources.delete(component.getId());\n}\n\n/**\n * Drops the target record. Bound to `(component)` by\n * `makeDropTarget` so the returned teardown closure stays a stable\n * named-function reference.\n */\nfunction tearDownDropTarget(component: Component): void {\n dropTargets.delete(component.getId());\n}\n\n/**\n * Records the pending press and arms the viewport-level move / up\n * listeners. Nothing visual happens until the cursor crosses the\n * threshold.\n *\n * Registered as a subtree mousedown listener on every drag source, so\n * a press on any descendant of the source bubbles up the subtree\n * walker and the framework's Event router applies `component` as\n * `this` for the matching source — the lookup that identifies which\n * source was pressed.\n */\nfunction onSourceMouseDown(this: Component, e: MouseEvent): void {\n if (activeSession !== null) {\n return;\n }\n\n if (e.button !== 0) {\n return;\n }\n\n const record = dragSources.get(this.getId());\n\n if (!record) {\n return;\n }\n\n const source = record.component;\n const options = record.options;\n\n activeSession = {\n source,\n sourceOptions: options,\n dragData: resolveDragData(options),\n startX: e.clientX,\n startY: e.clientY,\n committed: false,\n ghost: null,\n feedback: null,\n indicator: null,\n currentTarget: null,\n previousBodyCursor: DOM.source.getInlineStyle(DOM.source.getBody(), \"cursor\"),\n };\n\n // Viewport listeners route through Event.baseViewportListener, which stops\n // mouseup propagation at window capture phase whenever any viewport\n // listener for the type exists. A raw document-level mouseup binding would\n // race SpinButton-class registrants that already pre-empt mouseup at\n // capture and never fire.\n Event.addViewportListener(source, \"mousemove\", onMouseMove);\n Event.addViewportListener(source, \"mouseup\", onMouseUp);\n}\n\n/**\n * Builds the session's three overlay components and writes the page-\n * wide cursor. Called once on the first mousemove that crosses the\n * threshold.\n */\nfunction commitSession(session: DragSession): void {\n session.committed = true;\n\n const ghost = session.sourceOptions.ghostFactory\n ? session.sourceOptions.ghostFactory(session.source, session.dragData)\n : new DragGhost();\n\n session.ghost = ghost;\n session.feedback = new DragFeedback();\n session.indicator = new ReorderIndicator();\n\n if (typeof (ghost as unknown as { show?: () => void }).show === \"function\") {\n (ghost as unknown as { show: () => void }).show();\n } else {\n const el = ghost.getElement(true)!;\n\n DOM.sink.appendChild(DOM.source.getDocumentElement(), el);\n }\n\n if (session.sourceOptions.cursor) {\n DOM.sink.apply(DOM.source.getBody(), { style: { cursor: session.sourceOptions.cursor } });\n }\n}\n\n/**\n * Builds the immutable detail payload threaded through every\n * source / target callback for the current pointer position.\n */\nfunction buildDetail(session: DragSession, clientX: number, clientY: number): DragEventDetail {\n return {\n dragData: session.dragData,\n sourceId: session.source.getId(),\n clientX,\n clientY,\n };\n}\n\n/**\n * Hit-tests under the ghost (which is pointer-events-none) and returns\n * the registered drop target whose element is the first match in the\n * z-stack, or `null` when no registered target sits under the cursor.\n */\nfunction pickDropTarget(clientX: number, clientY: number): DropTargetRecord | null {\n const stack = DOM.source.elementsFromPoint(clientX, clientY);\n\n for (const el of stack) {\n const record = dropTargets.get(DOM.source.getId(el));\n\n if (record) {\n return record;\n }\n }\n\n return null;\n}\n\n/**\n * Detaches the validity tint from the previous target and fires its\n * `onDragLeave`. No-op when there is no previous target.\n */\nfunction leaveCurrentTarget(session: DragSession, detail: DragEventDetail): void {\n if (session.currentTarget === null) {\n return;\n }\n\n const prev = dropTargets.get(session.currentTarget.getId());\n\n if (prev && prev.options.onDragLeave) {\n prev.options.onDragLeave(detail);\n }\n\n if (session.feedback) {\n session.feedback.detach();\n }\n\n if (session.indicator) {\n session.indicator.detach();\n }\n\n session.currentTarget = null;\n}\n\n/**\n * Attaches the validity tint to the new target, calls `onDragOver`\n * once, and positions the reorder indicator if the callback returned a\n * y value.\n */\nfunction enterNewTarget(session: DragSession, target: DropTargetRecord, detail: DragEventDetail): void {\n const accepted = target.options.accepts(detail);\n\n if (session.feedback && !target.options.suppressValidityTint) {\n session.feedback.setValid(accepted);\n session.feedback.attachTo(target.component, target.options.feedbackHost);\n }\n\n if (!accepted) {\n session.currentTarget = target.component;\n\n return;\n }\n\n const hint = target.options.onDragOver?.(detail);\n\n if (typeof hint === \"number\" && session.indicator) {\n session.indicator.attachTo(target.component);\n session.indicator.setInsertionY(hint);\n } else if (session.indicator) {\n session.indicator.detach();\n }\n\n session.currentTarget = target.component;\n}\n\n/**\n * Drives the active session forward each frame: commits past the\n * threshold, moves the ghost, hands target changes to the\n * enter / leave helpers, and re-runs `onDragOver` while the cursor stays\n * inside the same target.\n *\n * @returns `true` while a drag session is live, consuming the move so nothing else\n * tracks the pointer; nothing when there is no session, so the move keeps propagating.\n */\nfunction onMouseMove(e: MouseEvent): Event.ListenerResult {\n if (activeSession === null) {\n return;\n }\n\n const session = activeSession;\n\n if (!session.committed) {\n const dx = e.clientX - session.startX;\n const dy = e.clientY - session.startY;\n\n if (dx * dx + dy * dy < DRAG_THRESHOLD * DRAG_THRESHOLD) {\n return true;\n }\n\n const startDetail = buildDetail(session, e.clientX, e.clientY);\n\n if (session.sourceOptions.onDragStart?.(startDetail) === false) {\n endSession(false, e.clientX, e.clientY);\n\n return true;\n }\n\n commitSession(session);\n Event.fireEvent(session.source, \"dragstart\", { detail: startDetail });\n }\n\n if (session.ghost) {\n const dragGhost = session.ghost as unknown as { moveTo?: (x: number, y: number) => void };\n\n if (typeof dragGhost.moveTo === \"function\") {\n dragGhost.moveTo(e.clientX + GHOST_OFFSET_X, e.clientY + GHOST_OFFSET_Y);\n } else {\n session.ghost.setX(e.clientX + GHOST_OFFSET_X);\n session.ghost.setY(e.clientY + GHOST_OFFSET_Y);\n }\n }\n\n const detail = buildDetail(session, e.clientX, e.clientY);\n const target = pickDropTarget(e.clientX, e.clientY);\n\n if (target === null) {\n leaveCurrentTarget(session, detail);\n\n return true;\n }\n\n if (session.currentTarget !== target.component) {\n leaveCurrentTarget(session, detail);\n enterNewTarget(session, target, detail);\n\n return true;\n }\n\n // Same target as last frame — re-check accepts so the feedback\n // tint stays accurate (the validity of a drop can change as the\n // cursor moves within the same target, e.g. crossing into a\n // descendant region the source isn't allowed to land on). Skip\n // onDragOver / reorder indicator entirely while the drop is\n // rejected.\n const accepted = target.options.accepts(detail);\n\n if (session.feedback && !target.options.suppressValidityTint) {\n session.feedback.setValid(accepted);\n }\n\n if (!accepted) {\n if (session.indicator) {\n session.indicator.detach();\n }\n\n return true;\n }\n\n const hint = target.options.onDragOver?.(detail);\n\n if (typeof hint === \"number\" && session.indicator) {\n session.indicator.attachTo(target.component);\n session.indicator.setInsertionY(hint);\n } else if (session.indicator) {\n session.indicator.detach();\n }\n\n return true;\n}\n\n/**\n * Commits the drop (if any) and tears down the session.\n *\n * @returns `true` when a drag session was live, consuming the release that ends it;\n * nothing when there is no session, so the release keeps propagating.\n */\nfunction onMouseUp(e: MouseEvent): Event.ListenerResult {\n if (activeSession === null) {\n return;\n }\n\n const session = activeSession;\n const detail = buildDetail(session, e.clientX, e.clientY);\n let dropped = false;\n\n if (session.committed && session.currentTarget !== null) {\n const target = dropTargets.get(session.currentTarget.getId());\n\n if (target) {\n // Released over a registered drop target. Dispatch the drop only\n // when the target accepts; either way the release was *handled* by a\n // target rather than falling through to empty space, so report\n // `dropped` so the source skips its empty-space fallback — e.g. a Tab\n // header snaps back instead of tearing off into a window when the\n // target refused it (a rejected self-dock is a no-op, not a detach).\n if (target.options.accepts(detail)) {\n const onDropResult = target.options.onDrop?.(detail);\n\n if (onDropResult !== false) {\n Event.fireEvent(session.source, \"drop\", { detail });\n }\n }\n\n dropped = true;\n }\n }\n\n endSession(dropped, e.clientX, e.clientY);\n\n return true;\n}\n\n/**\n * Removes overlays, unwires viewport listeners, restores the body\n * cursor, and fires `dragend` when the session committed.\n */\nfunction endSession(dropped: boolean, clientX: number, clientY: number): void {\n if (activeSession === null) {\n return;\n }\n\n const session = activeSession;\n\n Event.removeViewportListener(session.source, \"mousemove\", onMouseMove);\n Event.removeViewportListener(session.source, \"mouseup\", onMouseUp);\n\n // The drag chrome is built fresh for every committed gesture in\n // `commitSession` and held only on the session record — none of it is\n // registered through `addComponent`, so `Component.destructor()`'s child\n // recursion can never reach it. Disposing, rather than only detaching,\n // is what reclaims each one's per-instance stylesheet rule before the\n // session reference is dropped; detaching alone grew the shared sheet by\n // one rule per drag, without bound.\n if (session.feedback) {\n session.feedback.dispose();\n }\n\n if (session.indicator) {\n session.indicator.dispose();\n }\n\n if (session.ghost) {\n if (session.sourceOptions.ghostFactory) {\n // A ghost from the caller's factory belongs to the caller, which\n // may hand back the same component on every gesture — so it is\n // detached, never disposed.\n const dragGhost = session.ghost as unknown as { hide?: () => void };\n\n if (typeof dragGhost.hide === \"function\") {\n dragGhost.hide();\n } else {\n session.ghost.removeElement();\n }\n } else {\n session.ghost.dispose();\n }\n }\n\n if (session.sourceOptions.cursor) {\n DOM.sink.apply(DOM.source.getBody(), { style: { cursor: session.previousBodyCursor } });\n }\n\n if (session.committed) {\n const detail = buildDetail(session, clientX, clientY);\n\n Event.fireEvent(session.source, \"dragend\", { detail });\n session.sourceOptions.onDragEnd?.(detail, dropped);\n }\n\n activeSession = null;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DragManager-DRor_-1x.js","names":[],"sources":["../../src/typescript/lib/overlay/DragFeedback.ts","../../src/typescript/lib/overlay/DragGhost.ts","../../src/typescript/lib/overlay/ReorderIndicator.ts","../../src/typescript/lib/overlay/DragManager.ts"],"sourcesContent":["// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { Component } from \"~/core/Component.js\";\nimport { Position } from \"~/primitive/Position.js\";\nimport { callable } from \"~/core/Callable.js\";\nimport { LayerManager } from \"~/core/LayerManager.js\";\nimport { DOM } from \"~/core/DOM.js\";\n\n/**\n * Z-order for the drop-target validity tint. The tint highlights a drop target,\n * which lives in ordinary app content — so it must sit **below** the lowest\n * {@link LayerManager} band (the {@link Window} band) or it paints over a\n * floating window, while still sitting above the target's own content (app\n * z-indexes top out near 3). The app tree establishes no isolating stacking\n * context, so a higher value escapes to the root context and beats windows —\n * which is exactly the bug `Band.Window - 1` avoids. Shared rationale with\n * {@link ReorderIndicator}; the drag ghost sits above both at the root.\n */\nconst Z_INDEX = LayerManager.Band.Window - 1;\n\n/**\n * A validity tint overlay drawn on top of the row currently being hovered\n * during an active drag. The colour swaps between the `valid` and\n * `invalid` theme tokens via {@link setValid}; the geometry is mirrored\n * onto a drop target via {@link attachTo}.\n *\n * Owned by [`DragManager`](/api/overlay/variables/DragManager) — application\n * code does not instantiate this directly.\n *\n * @category Core\n */\nclass DragFeedback extends Component {\n\n private _valid: boolean = true;\n\n /**\n * Constructs a drag-feedback overlay. The overlay is not attached\n * until {@link attachTo} is called.\n */\n constructor() {\n super();\n\n this.setPosition(Position.ABSOLUTE);\n this.setZIndex(Z_INDEX);\n this.setPointerEvents(\"none\");\n\n this.applyTintForValidity();\n }\n\n /**\n * Returns whether the overlay is currently showing the \"valid drop\"\n * tint.\n *\n * @returns `true` for the valid tint, `false` for the invalid tint.\n */\n isValid(): boolean {\n return this._valid;\n }\n\n /**\n * Switches the overlay between the `valid` and `invalid` theme\n * tokens. Idempotent — repeated calls with the same value are a\n * no-op.\n *\n * @param valid - `true` to show the valid tint, `false` for invalid.\n */\n setValid(valid: boolean): void {\n if (this._valid === valid) {\n return;\n }\n\n this._valid = valid;\n\n this.applyTintForValidity();\n }\n\n /**\n * Sizes this overlay to cover the drop target and appends it to the DOM.\n *\n * With no `host`, the tint is a child of the target, covering its body. When\n * a `host` is given, the tint instead lives in that (non-scrolling) layer,\n * sized to the target's box within it — so a target that scrolls its own\n * content (a Tab strip's clip frame) gets a tint over the *viewport* that\n * stays put instead of riding the scroll.\n *\n * @param target - The drop target whose box the tint should cover.\n * @param host - Optional non-scrolling layer to host the tint (see\n * {@link DropTargetOptions.feedbackHost}). Defaults to the target.\n */\n attachTo(target: Component, host?: Component): void {\n const myEl = this.getElement(true)!;\n\n if (host && host !== target) {\n // Overlay the target's box from within the host layer.\n this.setX(target.getX());\n this.setY(target.getY());\n this.setWidth(target.getWidth());\n this.setHeight(target.getHeight());\n\n const hostEl = host.getElement(true)!;\n if (DOM.source.getParentElement(myEl) !== hostEl) {\n DOM.sink.appendChild(hostEl, myEl);\n }\n\n return;\n }\n\n // Cover the target's own body as a child of it.\n this.setX(0);\n this.setY(0);\n this.setWidth(target.getWidth());\n this.setHeight(target.getHeight());\n\n const targetEl = target.getElement(true)!;\n if (DOM.source.getParentElement(myEl) !== targetEl) {\n DOM.sink.appendChild(targetEl, myEl);\n }\n }\n\n /**\n * Removes the overlay element from the DOM.\n */\n detach(): void {\n this.removeElement();\n }\n\n /**\n * Writes the background and border CSS variables that correspond to\n * the cached validity state. Called from the constructor and from\n * {@link setValid} on transitions.\n */\n private applyTintForValidity(): void {\n const suffix = this._valid ? \"valid\" : \"invalid\";\n\n this.setBackgroundColor(`var(--ts-ui-drag-feedback-${suffix}-bg)`);\n this.setBorder({ border: `2px solid var(--ts-ui-drag-feedback-${suffix}-border)` });\n }\n}\n\nconst DragFeedbackCallable = callable(DragFeedback);\ntype DragFeedbackCallable = DragFeedback;\nexport {\n DragFeedback as _DragFeedback,\n DragFeedbackCallable as DragFeedback,\n};\n","// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { Component } from \"~/core/Component.js\";\nimport { Position } from \"~/primitive/Position.js\";\nimport { Text } from \"~/component/input/Text.js\";\nimport { callable } from \"~/core/Callable.js\";\nimport { DOM } from \"~/core/DOM.js\";\n\n/**\n * Z-order ceiling for the drag ghost. The follow-the-cursor preview rides above\n * everything during a drag — appended at the document root, above the\n * LayerManager bands — so it is never occluded by a floating window or by the\n * per-target highlights ([`DragFeedback`](/api/overlay/classes/DragFeedback) /\n * [`ReorderIndicator`](/api/overlay/classes/ReorderIndicator)), which deliberately\n * sit *below* the window band instead.\n */\nconst Z_INDEX = 10200;\n\n/**\n * Default ghost width when the caller omits an explicit size. Picked to\n * comfortably surround a one-line label without measuring text.\n */\nconst DEFAULT_WIDTH = 160;\n\n/** Default ghost height — one row's worth of vertical room. */\nconst DEFAULT_HEIGHT = 28;\n\n/**\n * Inner padding around the optional ghost label so text doesn't crowd the\n * border at the framework's default font size.\n */\nconst LABEL_INSET = 6;\n\n/**\n * A floating drag preview that follows the pointer during an active drag\n * session, drawn above every other overlay. Created and owned by\n * [`DragManager`](/api/overlay/variables/DragManager); application code does\n * not instantiate this directly.\n *\n * The ghost is `Position.FIXED` (one of the documented overlay carve-outs\n * in `ARCHITECTURE.md` §Positioning) and renders with\n * `pointer-events: none` so the manager's\n * `document.elementsFromPoint` hit-test always returns the row underneath.\n *\n * @category Core\n */\nclass DragGhost extends Component {\n\n private _label: Text | null = null;\n\n /**\n * Constructs a drag ghost. The caller positions it via\n * {@link moveTo} and toggles visibility through {@link show} /\n * {@link hide}.\n *\n * @param label - Optional text drawn inside the ghost.\n * @param width - Optional width in pixels (defaults to 160).\n * @param height - Optional height in pixels (defaults to 28).\n */\n constructor(label?: string, width?: number, height?: number) {\n super();\n\n this.setPosition(Position.FIXED);\n this.setZIndex(Z_INDEX);\n this.setPointerEvents(\"none\");\n this.setWidth(width ?? DEFAULT_WIDTH);\n this.setHeight(height ?? DEFAULT_HEIGHT);\n\n this.setBackgroundColor(\"var(--ts-ui-drag-ghost-bg)\");\n this.setBorder({ border: \"1px solid var(--ts-ui-drag-ghost-border)\" });\n this.setShadow(\"var(--ts-ui-drag-ghost-shadow)\");\n this.setBorderRadius(\"var(--ts-ui-border-radius, 4px)\");\n this.setOpacity(Number(\"0.85\"));\n\n if (label !== undefined) {\n this._label = new Text(label);\n this._label.setPointerEvents(\"none\");\n this.addComponent(this._label);\n }\n }\n\n /**\n * Repositions the ghost so its top-left corner sits at\n * `(clientX, clientY)`. `DragManager` calls this on every `mousemove`\n * during an active drag.\n *\n * @param clientX - The viewport X (already offset from the cursor by the manager).\n * @param clientY - The viewport Y (already offset from the cursor by the manager).\n */\n moveTo(clientX: number, clientY: number): void {\n this.setX(clientX);\n this.setY(clientY);\n }\n\n /**\n * Appends the ghost to `<html>` and schedules a layout pass. Used by\n * `DragManager` when a drag commits past the movement threshold.\n */\n show(): void {\n const el = this.getElement(true)!;\n\n this.scheduleLayout();\n DOM.sink.appendChild(DOM.source.getDocumentElement(), el);\n }\n\n /**\n * Removes the ghost element from the DOM. Used by `DragManager` on\n * mouseup / cancel.\n */\n hide(): void {\n this.removeElement();\n }\n\n /**\n * Lays out the optional label inside the ghost's content box.\n *\n * @returns This component, for method chaining.\n */\n doLayout(): this {\n super.doLayout();\n\n const box = this.getContentBounds();\n\n if (this._label && box) {\n this._label.setX(box.x + LABEL_INSET);\n this._label.setY(box.y + LABEL_INSET);\n this._label.setWidth(box.width - LABEL_INSET * 2);\n this._label.setHeight(box.height - LABEL_INSET * 2);\n }\n\n return this;\n }\n}\n\nconst DragGhostCallable = callable(DragGhost);\ntype DragGhostCallable = DragGhost;\nexport {\n DragGhost as _DragGhost,\n DragGhostCallable as DragGhost,\n};\n","// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { Component } from \"~/core/Component.js\";\nimport { Position } from \"~/primitive/Position.js\";\nimport { callable } from \"~/core/Callable.js\";\nimport { LayerManager } from \"~/core/LayerManager.js\";\nimport { DOM } from \"~/core/DOM.js\";\n\n/**\n * Z-order shared with {@link DragFeedback}: just **below** the lowest\n * {@link LayerManager} band (the {@link Window} band) so this drop-target\n * insertion line — drawn over app content that establishes no isolating\n * stacking context — never paints over a floating window, while still sitting\n * above the target's own content. The drag ghost sits above both at the root.\n */\nconst Z_INDEX = LayerManager.Band.Window - 1;\n\n/** Height of the insertion-line bar in pixels. */\nconst BAR_HEIGHT = 2;\n\n/**\n * Half the bar height — subtracted in {@link ReorderIndicator.setInsertionY}\n * so the 2 px bar is centred on the insertion line.\n */\nconst BAR_HALF = 1;\n\n/**\n * A 2 px horizontal bar drawn between rows to mark the insertion line\n * during an active drag-reorder gesture.\n *\n * Reserved for future sibling-reorder work — drop-on-directory does not\n * use this overlay. The class ships now so the public API surface and\n * theme tokens stabilise alongside\n * [`DragGhost`](/api/overlay/classes/DragGhost) and\n * [`DragFeedback`](/api/overlay/classes/DragFeedback); the row-DnD wiring\n * in [`TreeTable`](/api/component/table/classes/TreeTable) only attaches\n * the feedback tint.\n *\n * @category Core\n */\nclass ReorderIndicator extends Component {\n\n /**\n * Constructs a reorder indicator. The bar is not attached until\n * {@link attachTo} is called.\n */\n constructor() {\n super();\n\n this.setPosition(Position.ABSOLUTE);\n this.setZIndex(Z_INDEX);\n this.setPointerEvents(\"none\");\n this.setHeight(BAR_HEIGHT);\n\n this.setBackgroundColor(\"var(--ts-ui-drag-reorder-color)\");\n }\n\n /**\n * Centres the bar on the given y-coordinate within the attached\n * target. The `- BAR_HALF` shift accounts for the 2 px bar height.\n *\n * @param y - Insertion-line y, measured from the target's top edge.\n */\n setInsertionY(y: number): void {\n this.setY(y - BAR_HALF);\n }\n\n /**\n * Mirrors the target's width onto the bar and appends the bar\n * element to the target.\n *\n * @param target - The drop target whose top-left coordinate space\n * the bar is positioned within.\n */\n attachTo(target: Component): void {\n const targetEl = target.getElement(true)!;\n const myEl = this.getElement(true)!;\n\n this.setX(0);\n this.setWidth(target.getWidth());\n\n if (DOM.source.getParentElement(myEl) === targetEl) {\n return;\n }\n\n DOM.sink.appendChild(targetEl, myEl);\n }\n\n /**\n * Removes the bar element from the DOM.\n */\n detach(): void {\n this.removeElement();\n }\n}\n\nconst ReorderIndicatorCallable = callable(ReorderIndicator);\ntype ReorderIndicatorCallable = ReorderIndicator;\nexport {\n ReorderIndicator as _ReorderIndicator,\n ReorderIndicatorCallable as ReorderIndicator,\n};\n","// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { Component } from \"~/core/Component.js\";\nimport { DragFeedback } from \"~/overlay/DragFeedback.js\";\nimport { DragGhost } from \"~/overlay/DragGhost.js\";\nimport { Event } from \"~/core/Event.js\";\nimport { ReorderIndicator } from \"~/overlay/ReorderIndicator.js\";\nimport { DOM } from \"~/core/DOM.js\";\n\n/**\n * Arbitrary, caller-defined payload attached to a drag source — the\n * shape is consumer-domain and the manager never inspects fields.\n *\n * @category Core\n */\nexport type DragData = Record<string, unknown>;\n\n/**\n * Payload delivered to every named drag-source / drop-target callback\n * and to every fired DOM event. Field names are stable across\n * `dragstart`, `dragover`, `dragleave`, `drop`, `dragend`.\n *\n * @category Core\n */\nexport interface DragEventDetail {\n /** The source's resolved drag data — read from the source options at session start. */\n dragData : DragData;\n /** The source component's id (`getId()`), useful for cycle / self-drop checks. */\n sourceId : string;\n /** Viewport-relative pointer X at the moment the event was raised. */\n clientX : number;\n /** Viewport-relative pointer Y at the moment the event was raised. */\n clientY : number;\n}\n\n/**\n * Drag-data payload attached to every tab-header drag — the cross-container\n * contract shared by the within-strip reorder path, tab tear-off / re-dock, the\n * Ctrl-drag window re-dock, and the downstream edge-split / dock-manager work.\n * A drop target reads it off {@link DragEventDetail}'s `dragData`. Because\n * {@link DragData} is a plain record it cannot carry a live component reference,\n * so `componentId` keys into the module-level `tabDragRegistry` to resolve the\n * dragged content.\n *\n * @category Core\n */\nexport interface TabDragData {\n /** Discriminator a drop target tests in its `accepts` predicate. */\n tabDrag: true;\n /** The source strip's stable id — distinguishes reorder-within from dock-from-elsewhere. */\n sourceTabId: string;\n /** The dragged content component's id — the key into `tabDragRegistry`. */\n componentId: string;\n /** The tab label — used for the drag ghost and the tear-off window title. */\n label: string;\n}\n\n/**\n * Resolves a {@link TabDragData} `componentId` back to the live content\n * component being dragged. Written when a header drag starts and cleared when it\n * ends, so a drop target — the same strip, another strip, or a torn-off\n * {@link DragData}-carrying window — can move the real component rather than\n * only learning its id. Shared by-import across `Tab` and `Window`; one\n * instance, so a source-side write is visible to the destination-side read.\n */\nexport const tabDragRegistry: Map<string, Component> = new Map<string, Component>();\n\n/**\n * Dwell, in milliseconds, before a tab held over a drop target spring-loads a\n * raise of that target's host window — surfacing a backgrounded float so the user\n * can aim the drop. Shared by the two dock drop surfaces so a region body\n * ([`DockRegion`](/api/layout/classes/DockRegion)) and a tab bar\n * ([`TabBar`](/api/component/container/classes/TabBar)) raise on the same cadence.\n *\n * Long enough that brushing a drag across a background window in transit does not\n * raise it, short enough that a deliberate hover surfaces the target. Set above a\n * `MenuItem` submenu's 150ms hover delay because raising a whole window is a\n * heavier, more disruptive action than opening a submenu, so it should demand a\n * clearly deliberate pause.\n */\nexport const SPRING_RAISE_DELAY_MS = 1000;\n\n/**\n * Construction-time options accepted by {@link DragManager.makeDragSource}.\n *\n * @category Core\n */\nexport interface DragSourceOptions {\n /** Static or factory-produced payload attached to the session. */\n dragData : DragData | (() => DragData);\n /**\n * Optional veto callback fired the moment the threshold is crossed.\n * Return `false` to abort the drag before any overlay is shown.\n */\n onDragStart? : (detail: DragEventDetail) => boolean | void;\n /**\n * Optional ghost factory. The returned component is used in place of\n * the manager's default ghost (which carries no label and matches the\n * source's size). The component must be detached when returned.\n */\n ghostFactory?: (source: Component, data: DragData) => Component;\n /** CSS cursor applied to `<body>` while the drag is active. */\n cursor? : string;\n /**\n * Fired once the gesture ends, after any `onDrop`. `dropped` is `true` when\n * the release was handled by a registered drop target — whether the target\n * accepted the drop or refused it — and `false` only on a release over empty\n * space. Lets a source distinguish a release that landed on a target from a\n * fall-through to empty space (e.g. tab tear-off), the signal the `\"dragend\"`\n * DOM event alone cannot carry.\n */\n onDragEnd? : (detail: DragEventDetail, dropped: boolean) => void;\n}\n\n/**\n * Construction-time options accepted by {@link DragManager.makeDropTarget}.\n *\n * @category Core\n */\nexport interface DropTargetOptions {\n /**\n * Validity predicate. Returns `true` when the dragged source may\n * drop on this target; the visual feedback tint mirrors the result.\n */\n accepts : (detail: DragEventDetail) => boolean;\n /**\n * Optional hover callback. Return a number to position the\n * [`ReorderIndicator`](/api/overlay/classes/ReorderIndicator) at the\n * given y inside the target; return `null` / `undefined` for no\n * reorder line.\n */\n onDragOver? : (detail: DragEventDetail) => number | null | void;\n /** Optional leave callback (cursor exits target's box). */\n onDragLeave? : (detail: DragEventDetail) => void;\n /** Optional drop callback — return `false` to suppress the `drop` event. */\n onDrop? : (detail: DragEventDetail) => boolean | void;\n /**\n * Suppresses the whole-target validity tint\n * ([`DragFeedback`](/api/overlay/classes/DragFeedback)) for this target. Pass it\n * when the target paints its own positional validity feedback (e.g. a\n * [`DockRegion`](/api/layout/classes/DockRegion) colours the drop *zone*\n * blue/red in `onDragOver`) so the two don't stack into a tinted frame *and*\n * a tinted zone. `accepts` still governs whether `onDragOver`/`onDrop` fire.\n */\n suppressValidityTint?: boolean;\n /**\n * Optional non-scrolling layer to host the validity tint, sized to the\n * target's box within it. Pass it when the target scrolls its own content\n * (e.g. a Tab strip's clip frame) so the tint overlays the *viewport* and\n * stays put instead of riding the scroll. Defaults to the target itself.\n */\n feedbackHost?: Component;\n}\n\ninterface DragSourceRecord {\n component: Component;\n options: DragSourceOptions;\n}\n\ninterface DropTargetRecord {\n component: Component;\n options: DropTargetOptions;\n}\n\ninterface DragSession {\n source: Component;\n sourceOptions: DragSourceOptions;\n dragData: DragData;\n startX: number;\n startY: number;\n committed: boolean;\n ghost: Component | null;\n feedback: DragFeedback | null;\n indicator: ReorderIndicator | null;\n currentTarget: Component | null;\n previousBodyCursor: string;\n}\n\n/**\n * Distance the cursor must travel between `mousedown` and `mousemove`\n * before the press-and-drag commits to a drag. The 4 px slop matches\n * the standard HIG threshold on Windows and macOS — anything shorter\n * fires a drag on plain clicks; anything longer feels unresponsive.\n */\nconst DRAG_THRESHOLD = 4;\n\n/**\n * Diagonal offsets applied to the ghost's top-left corner so the cursor\n * stays clear of the preview. Matches Finder / VS Code placement.\n */\nconst GHOST_OFFSET_X = 12;\nconst GHOST_OFFSET_Y = 12;\n\nconst dragSources = new Map<string, DragSourceRecord>();\nconst dropTargets = new Map<string, DropTargetRecord>();\nlet activeSession: DragSession | null = null;\n\n/**\n * Process-wide drag-and-drop coordinator. Maintains the global source /\n * target registry, owns the single active drag session, and\n * positions the three overlay components\n * ([`DragGhost`](/api/overlay/classes/DragGhost),\n * [`DragFeedback`](/api/overlay/classes/DragFeedback),\n * [`ReorderIndicator`](/api/overlay/classes/ReorderIndicator)) above the\n * page during a drag.\n *\n * Consumers register through the two factory functions and receive a\n * teardown closure to unwire when the source / target component goes\n * away. The manager itself fires no events directly — every callback\n * lives on the option bag the caller passed to the factory.\n *\n * @example\n * ```typescript\n * const tearDownSrc = DragManager.makeDragSource(row, {\n * dragData: () => ({ recordId: row.getRecord()?.get('id') }),\n * });\n * const tearDownTgt = DragManager.makeDropTarget(folder, {\n * accepts: (d) => d.dragData.recordId !== folder.getRecord()?.get('id'),\n * onDrop: (d) => moveRecord(d.dragData.recordId, folder),\n * });\n * ```\n *\n * @category Core\n */\nexport namespace DragManager {\n\n /**\n * Registers a component as a drag source. The component's mousedown\n * event begins a pending drag session that commits once the cursor\n * travels past the 4 px movement threshold.\n *\n * @param component - The source component.\n * @param options - Drag source configuration.\n *\n * @returns A teardown function that removes the source registration\n * and the mousedown listener.\n */\n export function makeDragSource(component: Component, options: DragSourceOptions): () => void {\n dragSources.set(component.getId(), { component, options });\n component.addMouseDownSubtreeListener(onSourceMouseDown);\n\n return tearDownDragSource.bind(null, component);\n }\n\n /**\n * Registers a component as a drop target. The component is queried\n * for `accepts` during every `mousemove` while a drag is active and\n * receives the configured callbacks at the appropriate phases.\n *\n * @param component - The drop target.\n * @param options - Drop target configuration.\n *\n * @returns A teardown function that removes the target registration.\n */\n export function makeDropTarget(component: Component, options: DropTargetOptions): () => void {\n dropTargets.set(component.getId(), { component, options });\n\n return tearDownDropTarget.bind(null, component);\n }\n\n /**\n * Returns whether a drag is currently in progress (committed past\n * the 4 px movement threshold).\n *\n * @returns `true` while the ghost is visible; `false` otherwise.\n */\n export function isDragging(): boolean {\n return activeSession !== null && activeSession.committed;\n }\n\n /**\n * Aborts an in-flight drag. Mirrors a `mouseup` outside any drop\n * target — no drop callback fires; the session tears down.\n */\n export function cancel(): void {\n if (activeSession === null) {\n return;\n }\n\n endSession(false, 0, 0);\n }\n}\n\n/**\n * Resolves the source's drag-data payload — accepts either a literal or\n * a factory function on every drag start so callers can carry per-row\n * state without re-registering the source.\n */\nfunction resolveDragData(options: DragSourceOptions): DragData {\n return typeof options.dragData === \"function\" ? options.dragData() : options.dragData;\n}\n\n/**\n * Removes the per-component mousedown listener and drops the source\n * record. Bound to `(component)` by `makeDragSource` so the returned\n * teardown closure stays a stable named-function reference.\n */\nfunction tearDownDragSource(component: Component): void {\n component.removeMouseDownSubtreeListener(onSourceMouseDown);\n dragSources.delete(component.getId());\n}\n\n/**\n * Drops the target record. Bound to `(component)` by\n * `makeDropTarget` so the returned teardown closure stays a stable\n * named-function reference.\n */\nfunction tearDownDropTarget(component: Component): void {\n dropTargets.delete(component.getId());\n}\n\n/**\n * Records the pending press and arms the viewport-level move / up\n * listeners. Nothing visual happens until the cursor crosses the\n * threshold.\n *\n * Registered as a subtree mousedown listener on every drag source, so\n * a press on any descendant of the source bubbles up the subtree\n * walker and the framework's Event router applies `component` as\n * `this` for the matching source — the lookup that identifies which\n * source was pressed.\n */\nfunction onSourceMouseDown(this: Component, e: MouseEvent): void {\n if (activeSession !== null) {\n return;\n }\n\n if (e.button !== 0) {\n return;\n }\n\n const record = dragSources.get(this.getId());\n\n if (!record) {\n return;\n }\n\n const source = record.component;\n const options = record.options;\n\n activeSession = {\n source,\n sourceOptions: options,\n dragData: resolveDragData(options),\n startX: e.clientX,\n startY: e.clientY,\n committed: false,\n ghost: null,\n feedback: null,\n indicator: null,\n currentTarget: null,\n previousBodyCursor: DOM.source.getInlineStyle(DOM.source.getBody(), \"cursor\"),\n };\n\n // Viewport listeners route through Event.baseViewportListener, which stops\n // mouseup propagation at window capture phase whenever any viewport\n // listener for the type exists. A raw document-level mouseup binding would\n // race SpinButton-class registrants that already pre-empt mouseup at\n // capture and never fire.\n Event.addViewportListener(source, \"mousemove\", onMouseMove);\n Event.addViewportListener(source, \"mouseup\", onMouseUp);\n}\n\n/**\n * Builds the session's three overlay components and writes the page-\n * wide cursor. Called once on the first mousemove that crosses the\n * threshold.\n */\nfunction commitSession(session: DragSession): void {\n session.committed = true;\n\n const ghost = session.sourceOptions.ghostFactory\n ? session.sourceOptions.ghostFactory(session.source, session.dragData)\n : new DragGhost();\n\n session.ghost = ghost;\n session.feedback = new DragFeedback();\n session.indicator = new ReorderIndicator();\n\n if (typeof (ghost as unknown as { show?: () => void }).show === \"function\") {\n (ghost as unknown as { show: () => void }).show();\n } else {\n const el = ghost.getElement(true)!;\n\n DOM.sink.appendChild(DOM.source.getDocumentElement(), el);\n }\n\n if (session.sourceOptions.cursor) {\n DOM.sink.apply(DOM.source.getBody(), { style: { cursor: session.sourceOptions.cursor } });\n }\n}\n\n/**\n * Builds the immutable detail payload threaded through every\n * source / target callback for the current pointer position.\n */\nfunction buildDetail(session: DragSession, clientX: number, clientY: number): DragEventDetail {\n return {\n dragData: session.dragData,\n sourceId: session.source.getId(),\n clientX,\n clientY,\n };\n}\n\n/**\n * Hit-tests under the ghost (which is pointer-events-none) and returns\n * the registered drop target whose element is the first match in the\n * z-stack, or `null` when no registered target sits under the cursor.\n */\nfunction pickDropTarget(clientX: number, clientY: number): DropTargetRecord | null {\n const stack = DOM.source.elementsFromPoint(clientX, clientY);\n\n for (const el of stack) {\n const record = dropTargets.get(DOM.source.getId(el));\n\n if (record) {\n return record;\n }\n }\n\n return null;\n}\n\n/**\n * Detaches the validity tint from the previous target and fires its\n * `onDragLeave`. No-op when there is no previous target.\n */\nfunction leaveCurrentTarget(session: DragSession, detail: DragEventDetail): void {\n if (session.currentTarget === null) {\n return;\n }\n\n const prev = dropTargets.get(session.currentTarget.getId());\n\n if (prev && prev.options.onDragLeave) {\n prev.options.onDragLeave(detail);\n }\n\n if (session.feedback) {\n session.feedback.detach();\n }\n\n if (session.indicator) {\n session.indicator.detach();\n }\n\n session.currentTarget = null;\n}\n\n/**\n * Attaches the validity tint to the new target, calls `onDragOver`\n * once, and positions the reorder indicator if the callback returned a\n * y value.\n */\nfunction enterNewTarget(session: DragSession, target: DropTargetRecord, detail: DragEventDetail): void {\n const accepted = target.options.accepts(detail);\n\n if (session.feedback && !target.options.suppressValidityTint) {\n session.feedback.setValid(accepted);\n session.feedback.attachTo(target.component, target.options.feedbackHost);\n }\n\n if (!accepted) {\n session.currentTarget = target.component;\n\n return;\n }\n\n const hint = target.options.onDragOver?.(detail);\n\n if (typeof hint === \"number\" && session.indicator) {\n session.indicator.attachTo(target.component);\n session.indicator.setInsertionY(hint);\n } else if (session.indicator) {\n session.indicator.detach();\n }\n\n session.currentTarget = target.component;\n}\n\n/**\n * Drives the active session forward each frame: commits past the\n * threshold, moves the ghost, hands target changes to the\n * enter / leave helpers, and re-runs `onDragOver` while the cursor stays\n * inside the same target.\n *\n * @returns `true` while a drag session is live, consuming the move so nothing else\n * tracks the pointer; nothing when there is no session, so the move keeps propagating.\n */\nfunction onMouseMove(e: MouseEvent): Event.ListenerResult {\n if (activeSession === null) {\n return;\n }\n\n const session = activeSession;\n\n if (!session.committed) {\n const dx = e.clientX - session.startX;\n const dy = e.clientY - session.startY;\n\n if (dx * dx + dy * dy < DRAG_THRESHOLD * DRAG_THRESHOLD) {\n return true;\n }\n\n const startDetail = buildDetail(session, e.clientX, e.clientY);\n\n if (session.sourceOptions.onDragStart?.(startDetail) === false) {\n endSession(false, e.clientX, e.clientY);\n\n return true;\n }\n\n commitSession(session);\n Event.fireEvent(session.source, \"dragstart\", { detail: startDetail });\n }\n\n if (session.ghost) {\n const dragGhost = session.ghost as unknown as { moveTo?: (x: number, y: number) => void };\n\n if (typeof dragGhost.moveTo === \"function\") {\n dragGhost.moveTo(e.clientX + GHOST_OFFSET_X, e.clientY + GHOST_OFFSET_Y);\n } else {\n session.ghost.setX(e.clientX + GHOST_OFFSET_X);\n session.ghost.setY(e.clientY + GHOST_OFFSET_Y);\n }\n }\n\n const detail = buildDetail(session, e.clientX, e.clientY);\n const target = pickDropTarget(e.clientX, e.clientY);\n\n if (target === null) {\n leaveCurrentTarget(session, detail);\n\n return true;\n }\n\n if (session.currentTarget !== target.component) {\n leaveCurrentTarget(session, detail);\n enterNewTarget(session, target, detail);\n\n return true;\n }\n\n // Same target as last frame — re-check accepts so the feedback\n // tint stays accurate (the validity of a drop can change as the\n // cursor moves within the same target, e.g. crossing into a\n // descendant region the source isn't allowed to land on). Skip\n // onDragOver / reorder indicator entirely while the drop is\n // rejected.\n const accepted = target.options.accepts(detail);\n\n if (session.feedback && !target.options.suppressValidityTint) {\n session.feedback.setValid(accepted);\n }\n\n if (!accepted) {\n if (session.indicator) {\n session.indicator.detach();\n }\n\n return true;\n }\n\n const hint = target.options.onDragOver?.(detail);\n\n if (typeof hint === \"number\" && session.indicator) {\n session.indicator.attachTo(target.component);\n session.indicator.setInsertionY(hint);\n } else if (session.indicator) {\n session.indicator.detach();\n }\n\n return true;\n}\n\n/**\n * Commits the drop (if any) and tears down the session.\n *\n * @returns `true` when a drag session was live, consuming the release that ends it;\n * nothing when there is no session, so the release keeps propagating.\n */\nfunction onMouseUp(e: MouseEvent): Event.ListenerResult {\n if (activeSession === null) {\n return;\n }\n\n const session = activeSession;\n const detail = buildDetail(session, e.clientX, e.clientY);\n let dropped = false;\n\n if (session.committed && session.currentTarget !== null) {\n const target = dropTargets.get(session.currentTarget.getId());\n\n if (target) {\n // Released over a registered drop target. Dispatch the drop only\n // when the target accepts; either way the release was *handled* by a\n // target rather than falling through to empty space, so report\n // `dropped` so the source skips its empty-space fallback — e.g. a Tab\n // header snaps back instead of tearing off into a window when the\n // target refused it (a rejected self-dock is a no-op, not a detach).\n if (target.options.accepts(detail)) {\n const onDropResult = target.options.onDrop?.(detail);\n\n if (onDropResult !== false) {\n Event.fireEvent(session.source, \"drop\", { detail });\n }\n }\n\n dropped = true;\n }\n }\n\n endSession(dropped, e.clientX, e.clientY);\n\n return true;\n}\n\n/**\n * Removes overlays, unwires viewport listeners, restores the body\n * cursor, and fires `dragend` when the session committed.\n */\nfunction endSession(dropped: boolean, clientX: number, clientY: number): void {\n if (activeSession === null) {\n return;\n }\n\n const session = activeSession;\n\n Event.removeViewportListener(session.source, \"mousemove\", onMouseMove);\n Event.removeViewportListener(session.source, \"mouseup\", onMouseUp);\n\n // The drag chrome is built fresh for every committed gesture in\n // `commitSession` and held only on the session record — none of it is\n // registered through `addComponent`, so `Component.destructor()`'s child\n // recursion can never reach it. Disposing, rather than only detaching,\n // is what reclaims each one's per-instance stylesheet rule before the\n // session reference is dropped; detaching alone grew the shared sheet by\n // one rule per drag, without bound.\n if (session.feedback) {\n session.feedback.dispose();\n }\n\n if (session.indicator) {\n session.indicator.dispose();\n }\n\n if (session.ghost) {\n if (session.sourceOptions.ghostFactory) {\n // A ghost from the caller's factory belongs to the caller, which\n // may hand back the same component on every gesture — so it is\n // detached, never disposed.\n const dragGhost = session.ghost as unknown as { hide?: () => void };\n\n if (typeof dragGhost.hide === \"function\") {\n dragGhost.hide();\n } else {\n session.ghost.removeElement();\n }\n } else {\n session.ghost.dispose();\n }\n }\n\n if (session.sourceOptions.cursor) {\n DOM.sink.apply(DOM.source.getBody(), { style: { cursor: session.previousBodyCursor } });\n }\n\n if (session.committed) {\n const detail = buildDetail(session, clientX, clientY);\n\n Event.fireEvent(session.source, \"dragend\", { detail });\n session.sourceOptions.onDragEnd?.(detail, dropped);\n }\n\n activeSession = null;\n}\n"],"mappings":"kNAkBA,IAAM,EAAU,EAAa,KAAK,OAAS,EAarC,aAAN,cAA2B,CAAU,CAEjC,OAA0B,GAM1B,aAAc,CACV,MAAM,EAEN,KAAK,YAAY,EAAS,QAAQ,EAClC,KAAK,UAAU,CAAO,EACtB,KAAK,iBAAiB,MAAM,EAE5B,KAAK,qBAAqB,CAC9B,CAQA,SAAmB,CACf,OAAO,KAAK,MAChB,CASA,SAAS,EAAsB,CACvB,KAAK,SAAW,IAIpB,KAAK,OAAS,EAEd,KAAK,qBAAqB,EAC9B,CAeA,SAAS,EAAmB,EAAwB,CAChD,IAAM,EAAO,KAAK,WAAW,EAAI,EAEjC,GAAI,GAAQ,IAAS,EAAQ,CAEzB,KAAK,KAAK,EAAO,KAAK,CAAC,EACvB,KAAK,KAAK,EAAO,KAAK,CAAC,EACvB,KAAK,SAAS,EAAO,SAAS,CAAC,EAC/B,KAAK,UAAU,EAAO,UAAU,CAAC,EAEjC,IAAM,EAAS,EAAK,WAAW,EAAI,EAC/B,EAAI,OAAO,iBAAiB,CAAI,IAAM,GACtC,EAAI,KAAK,YAAY,EAAQ,CAAI,EAGrC,MACJ,CAGA,KAAK,KAAK,CAAC,EACX,KAAK,KAAK,CAAC,EACX,KAAK,SAAS,EAAO,SAAS,CAAC,EAC/B,KAAK,UAAU,EAAO,UAAU,CAAC,EAEjC,IAAM,EAAW,EAAO,WAAW,EAAI,EACnC,EAAI,OAAO,iBAAiB,CAAI,IAAM,GACtC,EAAI,KAAK,YAAY,EAAU,CAAI,CAE3C,CAKA,QAAe,CACX,KAAK,cAAc,CACvB,CAOA,sBAAqC,CACjC,IAAM,EAAS,KAAK,OAAS,QAAU,UAEvC,KAAK,mBAAmB,6BAA6B,EAAO,KAAK,EACjE,KAAK,UAAU,CAAE,OAAQ,uCAAuC,EAAO,SAAU,CAAC,CACtF,CACJ,EAEM,EAAuB,EAAS,YAAY,EC3H5C,EAAU,MAMV,EAAgB,IAGhB,EAAiB,GAMjB,EAAc,EAed,UAAN,cAAwB,CAAU,CAE9B,OAA8B,KAW9B,YAAY,EAAgB,EAAgB,EAAiB,CACzD,MAAM,EAEN,KAAK,YAAY,EAAS,KAAK,EAC/B,KAAK,UAAU,CAAO,EACtB,KAAK,iBAAiB,MAAM,EAC5B,KAAK,SAAS,GAAS,CAAa,EACpC,KAAK,UAAU,GAAU,CAAc,EAEvC,KAAK,mBAAmB,4BAA4B,EACpD,KAAK,UAAU,CAAE,OAAQ,0CAA2C,CAAC,EACrE,KAAK,UAAU,gCAAgC,EAC/C,KAAK,gBAAgB,iCAAiC,EACtD,KAAK,WAAW,GAAc,EAE1B,IAAU,IAAA,KACV,KAAK,OAAS,IAAI,EAAK,CAAK,EAC5B,KAAK,OAAO,iBAAiB,MAAM,EACnC,KAAK,aAAa,KAAK,MAAM,EAErC,CAUA,OAAO,EAAiB,EAAuB,CAC3C,KAAK,KAAK,CAAO,EACjB,KAAK,KAAK,CAAO,CACrB,CAMA,MAAa,CACT,IAAM,EAAK,KAAK,WAAW,EAAI,EAE/B,KAAK,eAAe,EACpB,EAAI,KAAK,YAAY,EAAI,OAAO,mBAAmB,EAAG,CAAE,CAC5D,CAMA,MAAa,CACT,KAAK,cAAc,CACvB,CAOA,UAAiB,CACb,MAAM,SAAS,EAEf,IAAM,EAAM,KAAK,iBAAiB,EASlC,OAPI,KAAK,QAAU,IACf,KAAK,OAAO,KAAK,EAAI,EAAI,CAAW,EACpC,KAAK,OAAO,KAAK,EAAI,EAAI,CAAW,EACpC,KAAK,OAAO,SAAS,EAAI,MAAQ,EAAc,CAAC,EAChD,KAAK,OAAO,UAAU,EAAI,OAAS,EAAc,CAAC,GAG/C,IACX,CACJ,EAEM,EAAoB,EAAS,SAAS,ECvHtC,EAAU,EAAa,KAAK,OAAS,EAGrC,EAAa,EAMb,EAAW,EAgBX,iBAAN,cAA+B,CAAU,CAMrC,aAAc,CACV,MAAM,EAEN,KAAK,YAAY,EAAS,QAAQ,EAClC,KAAK,UAAU,CAAO,EACtB,KAAK,iBAAiB,MAAM,EAC5B,KAAK,UAAU,CAAU,EAEzB,KAAK,mBAAmB,iCAAiC,CAC7D,CAQA,cAAc,EAAiB,CAC3B,KAAK,KAAK,EAAI,CAAQ,CAC1B,CASA,SAAS,EAAyB,CAC9B,IAAM,EAAW,EAAO,WAAW,EAAI,EACjC,EAAW,KAAK,WAAW,EAAI,EAErC,KAAK,KAAK,CAAC,EACX,KAAK,SAAS,EAAO,SAAS,CAAC,EAE3B,EAAI,OAAO,iBAAiB,CAAI,IAAM,GAI1C,EAAI,KAAK,YAAY,EAAU,CAAI,CACvC,CAKA,QAAe,CACX,KAAK,cAAc,CACvB,CACJ,EAEM,EAA2B,EAAS,gBAAgB,EC/B7C,EAA0C,IAAI,IAe9C,EAAwB,IAwG/B,EAAiB,EAMjB,EAAiB,GACjB,EAAiB,GAEjB,EAAc,IAAI,IAClB,EAAc,IAAI,IACpB,EAAoC,KA6BjC,eAaI,SAAS,eAAe,EAAsB,EAAwC,CAIzF,OAHA,EAAY,IAAI,EAAU,MAAM,EAAG,CAAE,YAAW,SAAQ,CAAC,EACzD,EAAU,4BAA4B,iBAAiB,EAEhD,mBAAmB,KAAK,KAAM,CAAS,CAClD,iCAYO,SAAS,eAAe,EAAsB,EAAwC,CAGzF,OAFA,EAAY,IAAI,EAAU,MAAM,EAAG,CAAE,YAAW,SAAQ,CAAC,EAElD,mBAAmB,KAAK,KAAM,CAAS,CAClD,iCAQO,SAAS,YAAsB,CAClC,OAAO,IAAkB,MAAQ,EAAc,SACnD,yBAMO,SAAS,QAAe,CACvB,IAAkB,MAItB,WAAW,GAAO,EAAG,CAAC,CAC1B,mBACH,AAAA,IAAA,CAAA,CAAD,EAOA,SAAS,gBAAgB,EAAsC,CAC3D,OAAO,OAAO,EAAQ,UAAa,WAAa,EAAQ,SAAS,EAAI,EAAQ,QACjF,CAOA,SAAS,mBAAmB,EAA4B,CACpD,EAAU,+BAA+B,iBAAiB,EAC1D,EAAY,OAAO,EAAU,MAAM,CAAC,CACxC,CAOA,SAAS,mBAAmB,EAA4B,CACpD,EAAY,OAAO,EAAU,MAAM,CAAC,CACxC,CAaA,SAAS,kBAAmC,EAAqB,CAK7D,GAJI,IAAkB,MAIlB,EAAE,SAAW,EACb,OAGJ,IAAM,EAAS,EAAY,IAAI,KAAK,MAAM,CAAC,EAE3C,GAAI,CAAC,EACD,OAGJ,IAAM,EAAU,EAAO,UACjB,EAAU,EAAO,QAEvB,EAAgB,CACZ,SACA,cAAe,EACf,SAAe,gBAAgB,CAAO,EACtC,OAAe,EAAE,QACjB,OAAe,EAAE,QACjB,UAAe,GACf,MAAe,KACf,SAAe,KACf,UAAe,KACf,cAAe,KACf,mBAAoB,EAAI,OAAO,eAAe,EAAI,OAAO,QAAQ,EAAG,QAAQ,CAChF,EAOA,EAAM,oBAAoB,EAAQ,YAAa,WAAW,EAC1D,EAAM,oBAAoB,EAAQ,UAAa,SAAS,CAC5D,CAOA,SAAS,cAAc,EAA4B,CAC/C,EAAQ,UAAY,GAEpB,IAAM,EAAQ,EAAQ,cAAc,aAC9B,EAAQ,cAAc,aAAa,EAAQ,OAAQ,EAAQ,QAAQ,EACnE,IAAI,EAMV,GAJA,EAAQ,MAAY,EACpB,EAAQ,SAAY,IAAI,EACxB,EAAQ,UAAY,IAAI,EAEpB,OAAQ,EAA2C,MAAS,WAC5D,EAA2C,KAAK,MAC7C,CACH,IAAM,EAAK,EAAM,WAAW,EAAI,EAEhC,EAAI,KAAK,YAAY,EAAI,OAAO,mBAAmB,EAAG,CAAE,CAC5D,CAEI,EAAQ,cAAc,QACtB,EAAI,KAAK,MAAM,EAAI,OAAO,QAAQ,EAAG,CAAE,MAAO,CAAE,OAAQ,EAAQ,cAAc,MAAO,CAAE,CAAC,CAEhG,CAMA,SAAS,YAAY,EAAsB,EAAiB,EAAkC,CAC1F,MAAO,CACH,SAAU,EAAQ,SAClB,SAAU,EAAQ,OAAO,MAAM,EAC/B,UACA,SACJ,CACJ,CAOA,SAAS,eAAe,EAAiB,EAA0C,CAC/E,IAAM,EAAQ,EAAI,OAAO,kBAAkB,EAAS,CAAO,EAE3D,IAAK,IAAM,KAAM,EAAO,CACpB,IAAM,EAAS,EAAY,IAAI,EAAI,OAAO,MAAM,CAAE,CAAC,EAEnD,GAAI,EACA,OAAO,CAEf,CAEA,OAAO,IACX,CAMA,SAAS,mBAAmB,EAAsB,EAA+B,CAC7E,GAAI,EAAQ,gBAAkB,KAC1B,OAGJ,IAAM,EAAO,EAAY,IAAI,EAAQ,cAAc,MAAM,CAAC,EAEtD,GAAQ,EAAK,QAAQ,aACrB,EAAK,QAAQ,YAAY,CAAM,EAG/B,EAAQ,UACR,EAAQ,SAAS,OAAO,EAGxB,EAAQ,WACR,EAAQ,UAAU,OAAO,EAG7B,EAAQ,cAAgB,IAC5B,CAOA,SAAS,eAAe,EAAsB,EAA0B,EAA+B,CACnG,IAAM,EAAW,EAAO,QAAQ,QAAQ,CAAM,EAO9C,GALI,EAAQ,UAAY,CAAC,EAAO,QAAQ,uBACpC,EAAQ,SAAS,SAAS,CAAQ,EAClC,EAAQ,SAAS,SAAS,EAAO,UAAW,EAAO,QAAQ,YAAY,GAGvE,CAAC,EAAU,CACX,EAAQ,cAAgB,EAAO,UAE/B,MACJ,CAEA,IAAM,EAAO,EAAO,QAAQ,aAAa,CAAM,EAE3C,OAAO,GAAS,UAAY,EAAQ,WACpC,EAAQ,UAAU,SAAS,EAAO,SAAS,EAC3C,EAAQ,UAAU,cAAc,CAAI,GAC7B,EAAQ,WACf,EAAQ,UAAU,OAAO,EAG7B,EAAQ,cAAgB,EAAO,SACnC,CAWA,SAAS,YAAY,EAAqC,CACtD,GAAI,IAAkB,KAClB,OAGJ,IAAM,EAAU,EAEhB,GAAI,CAAC,EAAQ,UAAW,CACpB,IAAM,EAAK,EAAE,QAAU,EAAQ,OACzB,EAAK,EAAE,QAAU,EAAQ,OAE/B,GAAI,EAAK,EAAK,EAAK,EAAK,EAAiB,EACrC,MAAO,GAGX,IAAM,EAAc,YAAY,EAAS,EAAE,QAAS,EAAE,OAAO,EAE7D,GAAI,EAAQ,cAAc,cAAc,CAAW,IAAM,GAGrD,OAFA,WAAW,GAAO,EAAE,QAAS,EAAE,OAAO,EAE/B,GAGX,cAAc,CAAO,EACrB,EAAM,UAAU,EAAQ,OAAQ,YAAa,CAAE,OAAQ,CAAY,CAAC,CACxE,CAEA,GAAI,EAAQ,MAAO,CACf,IAAM,EAAY,EAAQ,MAEtB,OAAO,EAAU,QAAW,WAC5B,EAAU,OAAO,EAAE,QAAU,EAAgB,EAAE,QAAU,CAAc,GAEvE,EAAQ,MAAM,KAAK,EAAE,QAAU,CAAc,EAC7C,EAAQ,MAAM,KAAK,EAAE,QAAU,CAAc,EAErD,CAEA,IAAM,EAAS,YAAY,EAAS,EAAE,QAAS,EAAE,OAAO,EAClD,EAAS,eAAe,EAAE,QAAS,EAAE,OAAO,EAElD,GAAI,IAAW,KAGX,OAFA,mBAAmB,EAAS,CAAM,EAE3B,GAGX,GAAI,EAAQ,gBAAkB,EAAO,UAIjC,OAHA,mBAAmB,EAAS,CAAM,EAClC,eAAe,EAAS,EAAQ,CAAM,EAE/B,GASX,IAAM,EAAW,EAAO,QAAQ,QAAQ,CAAM,EAM9C,GAJI,EAAQ,UAAY,CAAC,EAAO,QAAQ,sBACpC,EAAQ,SAAS,SAAS,CAAQ,EAGlC,CAAC,EAKD,OAJI,EAAQ,WACR,EAAQ,UAAU,OAAO,EAGtB,GAGX,IAAM,EAAO,EAAO,QAAQ,aAAa,CAAM,EAS/C,OAPI,OAAO,GAAS,UAAY,EAAQ,WACpC,EAAQ,UAAU,SAAS,EAAO,SAAS,EAC3C,EAAQ,UAAU,cAAc,CAAI,GAC7B,EAAQ,WACf,EAAQ,UAAU,OAAO,EAGtB,EACX,CAQA,SAAS,UAAU,EAAqC,CACpD,GAAI,IAAkB,KAClB,OAGJ,IAAM,EAAU,EACV,EAAU,YAAY,EAAS,EAAE,QAAS,EAAE,OAAO,EACrD,EAAY,GAEhB,GAAI,EAAQ,WAAa,EAAQ,gBAAkB,KAAM,CACrD,IAAM,EAAS,EAAY,IAAI,EAAQ,cAAc,MAAM,CAAC,EAExD,IAOI,EAAO,QAAQ,QAAQ,CAAM,GACR,EAAO,QAAQ,SAAS,CAAM,IAE9B,IACjB,EAAM,UAAU,EAAQ,OAAQ,OAAQ,CAAE,QAAO,CAAC,EAI1D,EAAU,GAElB,CAIA,OAFA,WAAW,EAAS,EAAE,QAAS,EAAE,OAAO,EAEjC,EACX,CAMA,SAAS,WAAW,EAAkB,EAAiB,EAAuB,CAC1E,GAAI,IAAkB,KAClB,OAGJ,IAAM,EAAU,EAoBhB,GAlBA,EAAM,uBAAuB,EAAQ,OAAQ,YAAa,WAAW,EACrE,EAAM,uBAAuB,EAAQ,OAAQ,UAAa,SAAS,EAS/D,EAAQ,UACR,EAAQ,SAAS,QAAQ,EAGzB,EAAQ,WACR,EAAQ,UAAU,QAAQ,EAG1B,EAAQ,MACR,GAAI,EAAQ,cAAc,aAAc,CAIpC,IAAM,EAAY,EAAQ,MAEtB,OAAO,EAAU,MAAS,WAC1B,EAAU,KAAK,EAEf,EAAQ,MAAM,cAAc,CAEpC,MACI,EAAQ,MAAM,QAAQ,EAQ9B,GAJI,EAAQ,cAAc,QACtB,EAAI,KAAK,MAAM,EAAI,OAAO,QAAQ,EAAG,CAAE,MAAO,CAAE,OAAQ,EAAQ,kBAAmB,CAAE,CAAC,EAGtF,EAAQ,UAAW,CACnB,IAAM,EAAS,YAAY,EAAS,EAAS,CAAO,EAEpD,EAAM,UAAU,EAAQ,OAAQ,UAAW,CAAE,QAAO,CAAC,EACrD,EAAQ,cAAc,YAAY,EAAQ,CAAO,CACrD,CAEA,EAAgB,IACpB"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{h as e,t}from"./Component-
|
|
2
|
-
//# sourceMappingURL=FieldDecorator-
|
|
1
|
+
import{h as e,t}from"./Component-fRQvgaEY.js";import{t as n}from"./Tooltip-Dro4DOZs.js";import{t as r}from"./Fit-CL1m1nIZ.js";var FieldDecorator=class extends t{constructor(e,t){super(),this.setLayoutManager(new r),this.clearInsets(),this.setBorderRadius(`var(--ts-ui-border-radius)`);let n=e.getPreferredSize();n?this.setPreferredSize({width:n.width,height:n.height}):this.setPreferredSize({width:e.getWidth(),height:e.getHeight()}),t.removeComponent(e),t.addComponent(this),this.addComponent(e)}showError(e){return this.setOutline(`2px solid var(--ts-ui-validation-error-border)`),n.attach(this,e,{background:`var(--ts-ui-validation-error-tooltip-bg)`,color:`var(--ts-ui-validation-error-tooltip-color)`,border:`var(--ts-ui-validation-error-tooltip-border)`}),this}clearError(){return this.clearOutline(),n.detach(this),this}},i=e(FieldDecorator);export{i as t};
|
|
2
|
+
//# sourceMappingURL=FieldDecorator-Bpx8J8n9.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FieldDecorator-
|
|
1
|
+
{"version":3,"file":"FieldDecorator-Bpx8J8n9.js","names":[],"sources":["../../src/typescript/lib/validation/FieldDecorator.ts"],"sourcesContent":["// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { Component } from '~/core/Component.js';\nimport { Fit } from '~/layout/Fit.js';\nimport { Tooltip } from '~/overlay/Tooltip.js';\nimport { callable } from \"~/core/Callable.js\";\n\n/**\n * A thin wrapper component that provides error visualisation for a field component.\n *\n * On construction the decorator removes the field from its current parent and inserts\n * itself in the parent, then re-adds the field as its own child. This means the error\n * border is applied to the decorator — never to the field itself — so the field's own\n * border is left untouched and removing the validation state is a clean one-step reset.\n *\n * @remarks Due to the framework's append-only `addComponent` API the decorator is\n * placed at the end of the parent's children rather than in the field's original slot.\n * A future `addComponentAt(index, component)` enhancement could address this.\n *\n * @category Validation\n */\nclass FieldDecorator extends Component {\n\n /**\n * Creates a decorator that wraps `field` inside `parent`.\n *\n * The field is removed from `parent` and the decorator is added in its place,\n * then the field is added as a child of the decorator.\n *\n * @param field - The UI component to decorate.\n * @param parent - The current parent container of `field`.\n */\n constructor(field: Component, parent: Component) {\n super();\n\n this.setLayoutManager(new Fit());\n\n // Every Component defaults to 4px insets on all sides. Zero them out so\n // the Fit layout gives the field the decorator's full content area.\n this.clearInsets();\n\n // Inherit the theme border radius so the outline follows the field's rounded corners.\n this.setBorderRadius('var(--ts-ui-border-radius)');\n\n // Mirror the field's preferred size so the parent layout allocates the\n // same space for the decorator as it did for the field. Without this,\n // layouts that fall back to a default width (e.g. HBox defaultComponentWidth)\n // would give the decorator a different — usually smaller — allocation.\n const ps = field.getPreferredSize();\n\n if (ps) {\n this.setPreferredSize({ width: ps.width, height: ps.height });\n } else {\n this.setPreferredSize({ width: field.getWidth(), height: field.getHeight() });\n }\n\n parent.removeComponent(field);\n parent.addComponent(this);\n this.addComponent(field);\n }\n\n /**\n * Applies a red validation-error outline to this decorator and attaches an error\n * tooltip that appears on hover.\n *\n * CSS `outline` is used instead of `border` so that the decorator's content area\n * and the wrapped field's size are completely unaffected — outline renders outside\n * the box model and takes up no layout space.\n *\n * @param message - The error message to display in the tooltip.\n */\n showError(message: string): this {\n this.setOutline('2px solid var(--ts-ui-validation-error-border)');\n\n Tooltip.attach(this, message, {\n background: 'var(--ts-ui-validation-error-tooltip-bg)',\n color : 'var(--ts-ui-validation-error-tooltip-color)',\n border : 'var(--ts-ui-validation-error-tooltip-border)',\n });\n\n return this;\n }\n\n /**\n * Removes the error outline and detaches the error tooltip.\n */\n clearError(): this {\n this.clearOutline();\n Tooltip.detach(this);\n\n return this;\n }\n}\n\nconst FieldDecoratorCallable = callable(FieldDecorator);\ntype FieldDecoratorCallable = FieldDecorator;\nexport {\n FieldDecorator as _FieldDecorator,\n FieldDecoratorCallable as FieldDecorator\n};\n"],"mappings":"8HAqBA,IAAM,eAAN,cAA6B,CAAU,CAWnC,YAAY,EAAkB,EAAmB,CAC7C,MAAM,EAEN,KAAK,iBAAiB,IAAI,CAAK,EAI/B,KAAK,YAAY,EAGjB,KAAK,gBAAgB,4BAA4B,EAMjD,IAAM,EAAK,EAAM,iBAAiB,EAE9B,EACA,KAAK,iBAAiB,CAAE,MAAO,EAAG,MAAO,OAAQ,EAAG,MAAO,CAAC,EAE5D,KAAK,iBAAiB,CAAE,MAAO,EAAM,SAAS,EAAG,OAAQ,EAAM,UAAU,CAAE,CAAC,EAGhF,EAAO,gBAAgB,CAAK,EAC5B,EAAO,aAAa,IAAI,EACxB,KAAK,aAAa,CAAK,CAC3B,CAYA,UAAU,EAAuB,CAS7B,OARA,KAAK,WAAW,gDAAgD,EAEhE,EAAQ,OAAO,KAAM,EAAS,CAC1B,WAAY,2CACZ,MAAY,8CACZ,OAAY,8CAChB,CAAC,EAEM,IACX,CAKA,YAAmB,CAIf,OAHA,KAAK,aAAa,EAClB,EAAQ,OAAO,IAAI,EAEZ,IACX,CACJ,EAEM,EAAyB,EAAS,cAAc"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{f as e,h as t,m as n}from"./Component-
|
|
2
|
-
//# sourceMappingURL=Fit-
|
|
1
|
+
import{f as e,h as t,m as n}from"./Component-fRQvgaEY.js";var Fit=class extends e{_fill=n.BOTH;constructor(e){super(),e&&this.applyOptions(e)}applyOptions(e){super.applyOptions(e),e.fill!==void 0&&this.setFill(e.fill)}getFill(){return this._fill}setFill(e){return this._fill=e,this}getPreferredSize(){return this.computeSize(e=>e.getPreferredSize())}getMinSize(){return this.computeSize(e=>e.getMinSize())}getMaxSize(){return this.computeSize(e=>e.getMaxSize())}computeSize(e){let t=this.getContainer();if(!t)return null;let n=t.getPerimeterSize(),r=n.left+n.right,i=n.top+n.bottom,a=t.getLaidOutComponents()[0]??null;if(!a)return null;let o=e(a);return o?{width:o.width+r,height:o.height+i}:null}getComponent(){let e=this.getContainer();if(!e)return null;let t=e.getComponents();if(t.length>1)throw Error(`Container contains more than one component.`);let n;return t.length==1&&(n=t[0]),n}computeTotalMinSize(){let e=this.getContainer();if(!e)return{width:0,height:0};let t=e.getLaidOutComponents()[0];return t?t.getMinSize()??{width:0,height:0}:{width:0,height:0}}doLayout(){let e=this.getContainer();if(!e)return;let t=e.getLaidOutComponents();if(t.length>1)throw Error(`Container contains more than one component.`);let n;if(t.length==1&&(n=t[0]),!n)return;let r=e.getInnerSize(),i=e.getContentInsets();r&&=this.inflateForOverflow(r),this.placeComponent(n,i?i.getLeft():0,i?i.getTop():0,r?r.width:0,r?r.height:0,this._fill)}},r=t(Fit);export{r as t};
|
|
2
|
+
//# sourceMappingURL=Fit-CL1m1nIZ.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Fit-DIYt2aQB.js","names":[],"sources":["../../src/typescript/lib/layout/Fit.ts"],"sourcesContent":["// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { LayoutManager, LayoutManagerOptions } from \"~/layout/LayoutManager.js\";\nimport { Size } from \"~/primitive/Size.js\";\nimport { FillType } from \"~/layout/FillType.js\";\nimport { Component } from \"~/core/Component.js\";\nimport { callable } from \"~/core/Callable.js\";\n\n/**\n * Construction-time options for {@link Fit}.\n *\n * @category Layouts\n */\nexport interface FitOptions extends LayoutManagerOptions {\n fill?: FillType;\n}\n\n/**\n * A layout manager that expects exactly one child component and positions it\n * inside the container's entire inner bounds. The default fill mode is\n * `FillType.BOTH` — the child stretches to fill the bounds. Pass\n * `fill: FillType.NONE` (or call {@link Fit.setFill}) to centre the child at\n * its preferred size instead; `HORIZONTAL` / `VERTICAL` stretch on one axis\n * and centre on the other. Throws if the container holds more than one\n * component.\n *\n * @category Layouts\n */\nclass Fit extends LayoutManager {\n\n private _fill: FillType = FillType.BOTH;\n\n constructor(options?: FitOptions) {\n // LayoutManager's constructor takes no options; applied via applyOptions below.\n // eslint-disable-next-line local/forward-super-options\n super();\n\n if (options) {\n this.applyOptions(options);\n }\n }\n\n /**\n * Applies a {@link FitOptions} bag, dispatching the fill mode after the\n * inherited LayoutManager defaults.\n *\n * @param options - The options bag carrying the values to apply.\n */\n protected applyOptions(options: FitOptions): void {\n super.applyOptions(options);\n\n if (options.fill !== undefined) {\n this.setFill(options.fill);\n }\n }\n\n /**\n * Returns the fill mode applied to the single child.\n *\n * @returns The current [`FillType`](/api/layout/enumerations/FillType).\n */\n getFill(): FillType {\n return this._fill;\n }\n\n /**\n * Sets the fill mode applied to the single child.\n *\n * @param fill - `BOTH` stretches the child to fill (default), `NONE`\n * centres it at its preferred size, `HORIZONTAL` / `VERTICAL` stretch on\n * one axis and centre on the other.\n *\n * @returns This layout manager, for method chaining.\n */\n setFill(fill: FillType): this {\n this._fill = fill;\n\n return this;\n }\n\n /**\n * Returns the preferred size of the single child component plus the container perimeter.\n *\n * @returns The preferred `{width, height}`, or `null` if there is no container or no displayed child.\n */\n getPreferredSize(): Size | null {\n return this.computeSize(component => component.getPreferredSize());\n }\n\n /**\n * Returns the minimum size of the single child component plus the container perimeter.\n *\n * @returns The minimum `{width, height}`, or `null` if there is no container or no displayed child.\n */\n getMinSize(): Size | null {\n return this.computeSize(component => component.getMinSize());\n }\n\n /**\n * Returns the maximum size of the single child component plus the container perimeter.\n *\n * @returns The maximum `{width, height}`, or `null` if there is no container or no displayed child.\n */\n getMaxSize(): Size | null {\n return this.computeSize(component => component.getMaxSize());\n }\n\n /**\n * Shared core of {@link getPreferredSize} / {@link getMinSize} /\n * {@link getMaxSize}: adds the displayed child's size (selected by `sizeOf`)\n * to the container perimeter.\n *\n * @param sizeOf - Selects the child's preferred, minimum, or maximum size.\n * @returns The composed `{width, height}`, or `null` if there is no\n * container, no displayed child, or the child reports no size.\n */\n private computeSize(sizeOf: (component: Component) => Size | null): Size | null {\n const container = this.getContainer();\n if (!container) {\n return null;\n }\n\n const perimeterSize = container.getPerimeterSize();\n\n const outerWidth = perimeterSize.left + perimeterSize.right;\n const outerHeight = perimeterSize.top + perimeterSize.bottom;\n\n // Size the displayed child only: a hidden sole child contributes no\n // size, so the Fit container reports none and its own parent reserves\n // nothing for it (honouring `displayed`, matching doLayout below).\n const component = container.getLaidOutComponents()[0] ?? null;\n if (!component) {\n return null;\n }\n\n const size = sizeOf(component);\n if (!size) {\n return null;\n }\n\n return {\n width: size.width + outerWidth,\n height: size.height + outerHeight\n };\n }\n\n /**\n * Returns the single child component of the container, or `undefined` if the container is empty.\n *\n * @returns The child component, or `undefined`.\n *\n * @remarks Throws if the container holds more than one component.\n */\n getComponent() {\n let container = this.getContainer();\n if (!container) {\n return null;\n }\n\n let components = container.getComponents();\n\n if (components.length > 1) {\n throw new Error(\"Container contains more than one component.\");\n }\n\n let component;\n\n if (components.length == 1) {\n component = components[0];\n }\n\n return component;\n }\n\n /**\n * Computes the children's combined minSize along this manager's geometry:\n * the single child's minSize. Used by `doLayout` to inflate the working\n * size when the host has opted into `setOverflowing`.\n *\n * @returns The single child's min-size; `{ width: 0, height: 0 }` when\n * the container is absent or empty.\n */\n protected computeTotalMinSize(): Size {\n const container = this.getContainer();\n if (!container) {\n return { width: 0, height: 0 };\n }\n\n const component = container.getLaidOutComponents()[0];\n if (!component) {\n return { width: 0, height: 0 };\n }\n\n const min = component.getMinSize();\n\n return min ?? { width: 0, height: 0 };\n }\n\n /**\n * Places the single child component inside the container's inner bounds\n * using the configured fill mode.\n *\n * @remarks Throws if the container holds more than one component. With\n * the default `FillType.BOTH` the child is sized to the full bounds;\n * with `FillType.NONE` it is placed at its preferred size and centred\n * via the inherited anchor-displacement logic in `placeComponent`.\n */\n doLayout() {\n let container = this.getContainer();\n if (!container) {\n return;\n }\n\n // Honour `displayed`: a hidden sole child contributes nothing and a\n // hidden first-of-two is skipped, so the visible child still fits.\n let components = container.getLaidOutComponents();\n\n if (components.length > 1) {\n throw new Error(\"Container contains more than one component.\");\n }\n\n let component;\n\n if (components.length == 1) {\n component = components[0];\n }\n\n if (!component) {\n return;\n }\n\n let containerSize = container.getInnerSize();\n let containerInsets = container.getContentInsets();\n\n // Universal scroll: see HBox.doLayout for the rationale. When the\n // host has marked the corresponding axis as overflowing, grow the\n // working size past the host's inner rect to the child's minSize so\n // the host's CSS `overflow: auto` produces a scrollbar.\n if (containerSize) {\n containerSize = this.inflateForOverflow(containerSize);\n }\n\n this.placeComponent(\n component,\n containerInsets ? containerInsets.getLeft() : 0,\n containerInsets ? containerInsets.getTop() : 0,\n containerSize ? containerSize.width : 0,\n containerSize ? containerSize.height : 0,\n this._fill\n );\n }\n}\n\nconst FitCallable = callable(Fit);\ntype FitCallable = Fit;\nexport {\n Fit as _Fit,\n FitCallable as Fit\n};\n"],"mappings":"0DA4BA,IAAM,IAAN,cAAkB,CAAc,CAE5B,MAA0B,EAAS,KAEnC,YAAY,EAAsB,CAG9B,MAAM,EAEF,GACA,KAAK,aAAa,CAAO,CAEjC,CAQA,aAAuB,EAA2B,CAC9C,MAAM,aAAa,CAAO,EAEtB,EAAQ,OAAS,IAAA,IACjB,KAAK,QAAQ,EAAQ,IAAI,CAEjC,CAOA,SAAoB,CAChB,OAAO,KAAK,KAChB,CAWA,QAAQ,EAAsB,CAG1B,MAFA,MAAK,MAAQ,EAEN,IACX,CAOA,kBAAgC,CAC5B,OAAO,KAAK,YAAY,GAAa,EAAU,iBAAiB,CAAC,CACrE,CAOA,YAA0B,CACtB,OAAO,KAAK,YAAY,GAAa,EAAU,WAAW,CAAC,CAC/D,CAOA,YAA0B,CACtB,OAAO,KAAK,YAAY,GAAa,EAAU,WAAW,CAAC,CAC/D,CAWA,YAAoB,EAA4D,CAC5E,IAAM,EAAY,KAAK,aAAa,EACpC,GAAI,CAAC,EACD,OAAO,KAGX,IAAM,EAAgB,EAAU,iBAAiB,EAE3C,EAAa,EAAc,KAAO,EAAc,MAChD,EAAc,EAAc,IAAM,EAAc,OAKhD,EAAY,EAAU,qBAAqB,CAAC,CAAC,IAAM,KACzD,GAAI,CAAC,EACD,OAAO,KAGX,IAAM,EAAO,EAAO,CAAS,EAK7B,OAJK,EAIE,CACH,MAAO,EAAK,MAAQ,EACpB,OAAQ,EAAK,OAAS,CAC1B,EANW,IAOf,CASA,cAAe,CACX,IAAI,EAAY,KAAK,aAAa,EAClC,GAAI,CAAC,EACD,OAAO,KAGX,IAAI,EAAa,EAAU,cAAc,EAEzC,GAAI,EAAW,OAAS,EACpB,MAAU,MAAM,6CAA6C,EAGjE,IAAI,EAMJ,OAJI,EAAW,QAAU,IACrB,EAAY,EAAW,IAGpB,CACX,CAUA,qBAAsC,CAClC,IAAM,EAAY,KAAK,aAAa,EACpC,GAAI,CAAC,EACD,MAAO,CAAE,MAAO,EAAG,OAAQ,CAAE,EAGjC,IAAM,EAAY,EAAU,qBAAqB,CAAC,CAAC,GAOnD,OANK,EAIO,EAAU,WAEf,GAAO,CAAE,MAAO,EAAG,OAAQ,CAAE,EALzB,CAAE,MAAO,EAAG,OAAQ,CAAE,CAMrC,CAWA,UAAW,CACP,IAAI,EAAY,KAAK,aAAa,EAClC,GAAI,CAAC,EACD,OAKJ,IAAI,EAAa,EAAU,qBAAqB,EAEhD,GAAI,EAAW,OAAS,EACpB,MAAU,MAAM,6CAA6C,EAGjE,IAAI,EAMJ,GAJI,EAAW,QAAU,IACrB,EAAY,EAAW,IAGvB,CAAC,EACD,OAGJ,IAAI,EAAgB,EAAU,aAAa,EACvC,EAAkB,EAAU,iBAAiB,EAMjD,AACI,IAAgB,KAAK,mBAAmB,CAAa,EAGzD,KAAK,eACD,EACA,EAAkB,EAAgB,QAAQ,EAAI,EAC9C,EAAkB,EAAgB,OAAO,EAAI,EAC7C,EAAgB,EAAc,MAAQ,EACtC,EAAgB,EAAc,OAAS,EACvC,KAAK,KACT,CACJ,CACJ,EAEM,EAAc,EAAS,GAAG"}
|
|
1
|
+
{"version":3,"file":"Fit-CL1m1nIZ.js","names":[],"sources":["../../src/typescript/lib/layout/Fit.ts"],"sourcesContent":["// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { LayoutManager, LayoutManagerOptions } from \"~/layout/LayoutManager.js\";\nimport { Size } from \"~/primitive/Size.js\";\nimport { FillType } from \"~/layout/FillType.js\";\nimport { Component } from \"~/core/Component.js\";\nimport { callable } from \"~/core/Callable.js\";\n\n/**\n * Construction-time options for {@link Fit}.\n *\n * @category Layouts\n */\nexport interface FitOptions extends LayoutManagerOptions {\n fill?: FillType;\n}\n\n/**\n * A layout manager that expects exactly one child component and positions it\n * inside the container's entire inner bounds. The default fill mode is\n * `FillType.BOTH` — the child stretches to fill the bounds. Pass\n * `fill: FillType.NONE` (or call {@link Fit.setFill}) to centre the child at\n * its preferred size instead; `HORIZONTAL` / `VERTICAL` stretch on one axis\n * and centre on the other. Throws if the container holds more than one\n * component.\n *\n * @category Layouts\n */\nclass Fit extends LayoutManager {\n\n private _fill: FillType = FillType.BOTH;\n\n constructor(options?: FitOptions) {\n // LayoutManager's constructor takes no options; applied via applyOptions below.\n // eslint-disable-next-line local/forward-super-options\n super();\n\n if (options) {\n this.applyOptions(options);\n }\n }\n\n /**\n * Applies a {@link FitOptions} bag, dispatching the fill mode after the\n * inherited LayoutManager defaults.\n *\n * @param options - The options bag carrying the values to apply.\n */\n protected applyOptions(options: FitOptions): void {\n super.applyOptions(options);\n\n if (options.fill !== undefined) {\n this.setFill(options.fill);\n }\n }\n\n /**\n * Returns the fill mode applied to the single child.\n *\n * @returns The current [`FillType`](/api/layout/enumerations/FillType).\n */\n getFill(): FillType {\n return this._fill;\n }\n\n /**\n * Sets the fill mode applied to the single child.\n *\n * @param fill - `BOTH` stretches the child to fill (default), `NONE`\n * centres it at its preferred size, `HORIZONTAL` / `VERTICAL` stretch on\n * one axis and centre on the other.\n *\n * @returns This layout manager, for method chaining.\n */\n setFill(fill: FillType): this {\n this._fill = fill;\n\n return this;\n }\n\n /**\n * Returns the preferred size of the single child component plus the container perimeter.\n *\n * @returns The preferred `{width, height}`, or `null` if there is no container or no displayed child.\n */\n getPreferredSize(): Size | null {\n return this.computeSize(component => component.getPreferredSize());\n }\n\n /**\n * Returns the minimum size of the single child component plus the container perimeter.\n *\n * @returns The minimum `{width, height}`, or `null` if there is no container or no displayed child.\n */\n getMinSize(): Size | null {\n return this.computeSize(component => component.getMinSize());\n }\n\n /**\n * Returns the maximum size of the single child component plus the container perimeter.\n *\n * @returns The maximum `{width, height}`, or `null` if there is no container or no displayed child.\n */\n getMaxSize(): Size | null {\n return this.computeSize(component => component.getMaxSize());\n }\n\n /**\n * Shared core of {@link getPreferredSize} / {@link getMinSize} /\n * {@link getMaxSize}: adds the displayed child's size (selected by `sizeOf`)\n * to the container perimeter.\n *\n * @param sizeOf - Selects the child's preferred, minimum, or maximum size.\n * @returns The composed `{width, height}`, or `null` if there is no\n * container, no displayed child, or the child reports no size.\n */\n private computeSize(sizeOf: (component: Component) => Size | null): Size | null {\n const container = this.getContainer();\n if (!container) {\n return null;\n }\n\n const perimeterSize = container.getPerimeterSize();\n\n const outerWidth = perimeterSize.left + perimeterSize.right;\n const outerHeight = perimeterSize.top + perimeterSize.bottom;\n\n // Size the displayed child only: a hidden sole child contributes no\n // size, so the Fit container reports none and its own parent reserves\n // nothing for it (honouring `displayed`, matching doLayout below).\n const component = container.getLaidOutComponents()[0] ?? null;\n if (!component) {\n return null;\n }\n\n const size = sizeOf(component);\n if (!size) {\n return null;\n }\n\n return {\n width: size.width + outerWidth,\n height: size.height + outerHeight\n };\n }\n\n /**\n * Returns the single child component of the container, or `undefined` if the container is empty.\n *\n * @returns The child component, or `undefined`.\n *\n * @remarks Throws if the container holds more than one component.\n */\n getComponent() {\n let container = this.getContainer();\n if (!container) {\n return null;\n }\n\n let components = container.getComponents();\n\n if (components.length > 1) {\n throw new Error(\"Container contains more than one component.\");\n }\n\n let component;\n\n if (components.length == 1) {\n component = components[0];\n }\n\n return component;\n }\n\n /**\n * Computes the children's combined minSize along this manager's geometry:\n * the single child's minSize. Used by `doLayout` to inflate the working\n * size when the host has opted into `setOverflowing`.\n *\n * @returns The single child's min-size; `{ width: 0, height: 0 }` when\n * the container is absent or empty.\n */\n protected computeTotalMinSize(): Size {\n const container = this.getContainer();\n if (!container) {\n return { width: 0, height: 0 };\n }\n\n const component = container.getLaidOutComponents()[0];\n if (!component) {\n return { width: 0, height: 0 };\n }\n\n const min = component.getMinSize();\n\n return min ?? { width: 0, height: 0 };\n }\n\n /**\n * Places the single child component inside the container's inner bounds\n * using the configured fill mode.\n *\n * @remarks Throws if the container holds more than one component. With\n * the default `FillType.BOTH` the child is sized to the full bounds;\n * with `FillType.NONE` it is placed at its preferred size and centred\n * via the inherited anchor-displacement logic in `placeComponent`.\n */\n doLayout() {\n let container = this.getContainer();\n if (!container) {\n return;\n }\n\n // Honour `displayed`: a hidden sole child contributes nothing and a\n // hidden first-of-two is skipped, so the visible child still fits.\n let components = container.getLaidOutComponents();\n\n if (components.length > 1) {\n throw new Error(\"Container contains more than one component.\");\n }\n\n let component;\n\n if (components.length == 1) {\n component = components[0];\n }\n\n if (!component) {\n return;\n }\n\n let containerSize = container.getInnerSize();\n let containerInsets = container.getContentInsets();\n\n // Universal scroll: see HBox.doLayout for the rationale. When the\n // host has marked the corresponding axis as overflowing, grow the\n // working size past the host's inner rect to the child's minSize so\n // the host's CSS `overflow: auto` produces a scrollbar.\n if (containerSize) {\n containerSize = this.inflateForOverflow(containerSize);\n }\n\n this.placeComponent(\n component,\n containerInsets ? containerInsets.getLeft() : 0,\n containerInsets ? containerInsets.getTop() : 0,\n containerSize ? containerSize.width : 0,\n containerSize ? containerSize.height : 0,\n this._fill\n );\n }\n}\n\nconst FitCallable = callable(Fit);\ntype FitCallable = Fit;\nexport {\n Fit as _Fit,\n FitCallable as Fit\n};\n"],"mappings":"0DA4BA,IAAM,IAAN,cAAkB,CAAc,CAE5B,MAA0B,EAAS,KAEnC,YAAY,EAAsB,CAG9B,MAAM,EAEF,GACA,KAAK,aAAa,CAAO,CAEjC,CAQA,aAAuB,EAA2B,CAC9C,MAAM,aAAa,CAAO,EAEtB,EAAQ,OAAS,IAAA,IACjB,KAAK,QAAQ,EAAQ,IAAI,CAEjC,CAOA,SAAoB,CAChB,OAAO,KAAK,KAChB,CAWA,QAAQ,EAAsB,CAG1B,MAFA,MAAK,MAAQ,EAEN,IACX,CAOA,kBAAgC,CAC5B,OAAO,KAAK,YAAY,GAAa,EAAU,iBAAiB,CAAC,CACrE,CAOA,YAA0B,CACtB,OAAO,KAAK,YAAY,GAAa,EAAU,WAAW,CAAC,CAC/D,CAOA,YAA0B,CACtB,OAAO,KAAK,YAAY,GAAa,EAAU,WAAW,CAAC,CAC/D,CAWA,YAAoB,EAA4D,CAC5E,IAAM,EAAY,KAAK,aAAa,EACpC,GAAI,CAAC,EACD,OAAO,KAGX,IAAM,EAAgB,EAAU,iBAAiB,EAE3C,EAAa,EAAc,KAAO,EAAc,MAChD,EAAc,EAAc,IAAM,EAAc,OAKhD,EAAY,EAAU,qBAAqB,CAAC,CAAC,IAAM,KACzD,GAAI,CAAC,EACD,OAAO,KAGX,IAAM,EAAO,EAAO,CAAS,EAK7B,OAJK,EAIE,CACH,MAAO,EAAK,MAAQ,EACpB,OAAQ,EAAK,OAAS,CAC1B,EANW,IAOf,CASA,cAAe,CACX,IAAI,EAAY,KAAK,aAAa,EAClC,GAAI,CAAC,EACD,OAAO,KAGX,IAAI,EAAa,EAAU,cAAc,EAEzC,GAAI,EAAW,OAAS,EACpB,MAAU,MAAM,6CAA6C,EAGjE,IAAI,EAMJ,OAJI,EAAW,QAAU,IACrB,EAAY,EAAW,IAGpB,CACX,CAUA,qBAAsC,CAClC,IAAM,EAAY,KAAK,aAAa,EACpC,GAAI,CAAC,EACD,MAAO,CAAE,MAAO,EAAG,OAAQ,CAAE,EAGjC,IAAM,EAAY,EAAU,qBAAqB,CAAC,CAAC,GAOnD,OANK,EAIO,EAAU,WAEf,GAAO,CAAE,MAAO,EAAG,OAAQ,CAAE,EALzB,CAAE,MAAO,EAAG,OAAQ,CAAE,CAMrC,CAWA,UAAW,CACP,IAAI,EAAY,KAAK,aAAa,EAClC,GAAI,CAAC,EACD,OAKJ,IAAI,EAAa,EAAU,qBAAqB,EAEhD,GAAI,EAAW,OAAS,EACpB,MAAU,MAAM,6CAA6C,EAGjE,IAAI,EAMJ,GAJI,EAAW,QAAU,IACrB,EAAY,EAAW,IAGvB,CAAC,EACD,OAGJ,IAAI,EAAgB,EAAU,aAAa,EACvC,EAAkB,EAAU,iBAAiB,EAMjD,AACI,IAAgB,KAAK,mBAAmB,CAAa,EAGzD,KAAK,eACD,EACA,EAAkB,EAAgB,QAAQ,EAAI,EAC9C,EAAkB,EAAgB,OAAO,EAAI,EAC7C,EAAgB,EAAc,MAAQ,EACtC,EAAgB,EAAc,OAAS,EACvC,KAAK,KACT,CACJ,CACJ,EAEM,EAAc,EAAS,GAAG"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{t as e}from"./DOM-67StIm5G.js";import{b as t,h as n,t as r,v as i}from"./Component-
|
|
2
|
-
//# sourceMappingURL=Glyph-
|
|
1
|
+
import{t as e}from"./DOM-67StIm5G.js";import{b as t,h as n,t as r,v as i}from"./Component-fRQvgaEY.js";var a=new Map;a.set(`unicode-arrow-up`,{kind:`char`,char:`▲`}),a.set(`unicode-arrow-down`,{kind:`char`,char:`▼`}),a.set(`unicode-arrow-left`,{kind:`char`,char:`◀`}),a.set(`unicode-arrow-right`,{kind:`char`,char:`▶`});var o=`http://www.w3.org/2000/svg`,s=`ts-glyph-`,c=!1,l=null;function registerGlyph(e){a.set(e.name,e),e.kind===`svg`&&c&&_addSymbolToSprite(e.name,e)}function unregisterGlyph(e){let t=a.get(e);a.delete(e),t&&t.kind===`svg`&&c&&_removeSymbolFromSprite(e)}function lookupGlyph(e){return a.get(e)}function ensureGlyphSprite(){if(c)return;let t=e.sink.createElementNS(o,`svg`);e.sink.apply(t,{setAttr:{"aria-hidden":`true`,focusable:`false`},style:{position:`absolute`,width:`0`,height:`0`,overflow:`hidden`}}),e.sink.appendChild(e.source.getBody(),t),l=t,c=!0}function ensureGlyphSymbolMounted(e){if(!c)return;let t=a.get(e);t&&t.kind===`svg`&&_addSymbolToSprite(e,t)}function _addSymbolToSprite(t,n){if(!l||n.kind!==`svg`)return;let r=s+t;if(e.source.querySelector(l,`#${e.source.escapeSelector(r)}`))return;let i=e.sink.createElementNS(o,`symbol`);e.sink.apply(i,{setAttr:{id:r,viewBox:n.viewBox}});let a=e.sink.createElementNS(o,`path`);e.sink.apply(a,{setAttr:{d:n.path}}),e.sink.appendChild(i,a),e.sink.appendChild(l,i)}function _removeSymbolFromSprite(t){if(!l)return;let n=s+t,r=e.source.querySelector(l,`#${e.source.escapeSelector(n)}`);if(r){let t=e.source.querySelector(r,`path`);e.sink.removeChild(l,r),e.sink.release(r),t&&e.sink.release(t)}}var u=`ts-ui-glyph-`,d=new Set,f=!1;function ensureGlyphKeyframes(){f||(f=!0,t.ensureKeyframes(`ts-ui-glyph-spin`,`from { transform: rotate(0deg); } to { transform: rotate(360deg); }`),t.ensureKeyframes(`ts-ui-glyph-pulse`,`0%, 12.5% { transform: rotate(0deg); } 12.5%, 25% { transform: rotate(45deg); } 25%, 37.5% { transform: rotate(90deg); } 37.5%, 50% { transform: rotate(135deg); } 50%, 62.5% { transform: rotate(180deg); } 62.5%, 75% { transform: rotate(225deg); } 75%, 87.5% { transform: rotate(270deg); } 87.5%, 100% { transform: rotate(315deg); }`),t.ensureKeyframes(`ts-ui-glyph-beat`,`0%, 90% { transform: scale(1); } 45% { transform: scale(1.25); }`),new t({scope:`class`,name:`ts-ui-glyph-spin`,styles:{animation:`ts-ui-glyph-spin var(--ts-ui-glyph-spin-duration, 2000ms) linear infinite`}}),new t({scope:`class`,name:`ts-ui-glyph-pulse`,styles:{animation:`ts-ui-glyph-pulse var(--ts-ui-glyph-pulse-duration, 1000ms) steps(8) infinite`}}),new t({scope:`class`,name:`ts-ui-glyph-beat`,styles:{animation:`ts-ui-glyph-beat var(--ts-ui-glyph-beat-duration, 1000ms) ease-in-out infinite`}}))}function _onReducedMotionChange(){for(let e of Array.from(d)){let t=e.deref();if(!t){d.delete(e);continue}t._syncReducedMotion()}}e.source.matchMedia(`(prefers-reduced-motion: reduce)`).addChangeListener(_onReducedMotionChange);var p={preferredSize:{width:16,height:16},tag:`span`},Glyph=class extends r{_name;_def;static register(...e){for(let t of e)registerGlyph(t)}static unregister(e){unregisterGlyph(e)}constructor(e,t,n){let r=lookupGlyph(e);if(!r)throw Error(`Unknown glyph: `+e);super(t,{...p,...n??{}}),this._name=e,this._def=r,r.kind===`char`&&(this._options.lineHeight===void 0&&this.setLineHeight(`1`),this._options.textAlign===void 0&&this.setTextAlign(`center`))}setPreferredSize(e){return super.setPreferredSize(e),super.setMinSize(e),super.setMaxSize(e),this}getBaseline(){let e=this.getPreferredSize();return e?e.height-3:null}getGlyphName(){return this._name}getFontSize(){return this._options.fontSize??null}setFontSize(e){return this._options.fontSize=e,this.setElementCSSRule(`fontSize`,e+`px`),this}getLineHeight(){let e=this._options.lineHeight;return e===void 0?null:typeof e==`number`?e+`px`:e}setLineHeight(e){return this._options.lineHeight=e,this.setElementCSSRule(`lineHeight`,typeof e==`number`?e+`px`:e),this}getTextAlign(){return this._options.textAlign??null}setTextAlign(e){return this._options.textAlign=e,this.setElementCSSRule(`textAlign`,e),this}getAnimated(){return this._glyphAnimation}setAnimated(t){if(this._glyphAnimation===t)return this;let n=this._glyphAnimation;this._glyphAnimation=t;let r=this.getElement();return r&&n&&e.sink.apply(r,{removeClass:[u+n]}),t===null?(this.setElementCSSRule(`animationDuration`,null),this._animatedRef&&=(d.delete(this._animatedRef),null),this):(ensureGlyphKeyframes(),this._animatedRef||(this._animatedRef=new WeakRef(this),d.add(this._animatedRef)),!i.isReducedMotion()&&r&&e.sink.apply(r,{addClass:[u+t]}),this._glyphAnimationDuration>0&&this.setElementCSSRule(`animationDuration`,this._glyphAnimationDuration+`ms`),this)}clearAnimated(){return this.setAnimated(null)}onEffectiveVisibilityChange(e){super.onEffectiveVisibilityChange(e),this._glyphAnimation!=null&&this.setAnimationPlayState(e?null:`paused`)}getAnimationDuration(){return this._glyphAnimationDuration}setAnimationDuration(e){return this._glyphAnimationDuration=e,this._glyphAnimation!=null&&!i.isReducedMotion()&&this.setElementCSSRule(`animationDuration`,e>0?e+`ms`:null),this}_syncReducedMotion(){let t=this._glyphAnimation;if(!t)return;let n=this.getElement(!0),r=u+t;i.isReducedMotion()?(e.sink.apply(n,{removeClass:[r]}),this.setElementCSSRule(`animationDuration`,null)):(e.sink.apply(n,{addClass:[r]}),this._glyphAnimationDuration>0&&this.setElementCSSRule(`animationDuration`,this._glyphAnimationDuration+`ms`))}applyOptions(e){super.applyOptions(e),e.fontSize!==void 0&&this.setFontSize(e.fontSize),e.lineHeight!==void 0&&this.setLineHeight(e.lineHeight),e.textAlign!==void 0&&this.setTextAlign(e.textAlign),e.animationDuration!==void 0&&this.setAnimationDuration(e.animationDuration);let t=this.getPreferredSizeConstraint();return t&&(e.minSize===void 0&&this.setMinSize({width:t.width,height:t.height}),e.maxSize===void 0&&this.setMaxSize({width:t.width,height:t.height})),e.animation!==void 0&&this.setAnimated(e.animation),this}createRootElement(){let t=super.createRootElement();if(this._def.kind!==`svg`)return t;ensureGlyphSprite(),ensureGlyphSymbolMounted(this._name);let n=`http://www.w3.org/2000/svg`,r=e.sink.createElementNS(n,`svg`);e.sink.apply(r,{style:{position:`absolute`,left:`0`,top:`0`,width:`100%`,height:`100%`,display:`block`},setAttr:{fill:`currentColor`,"aria-hidden":`true`,focusable:`false`}});let i=e.sink.createElementNS(n,`use`);return e.sink.apply(i,{setAttr:{href:`#`+s+this._name}}),e.sink.appendChild(r,i),e.sink.appendChild(t,r),this.trackHandle(r),this.trackHandle(i),t}render(){let t=super.render();this._def.kind===`char`&&e.sink.apply(t,{text:this._def.char}),this._glyphAnimation&&!i.isReducedMotion()&&e.sink.apply(t,{addClass:[u+this._glyphAnimation]});let n=this._options.preferredSize;return n&&(this.setElementStyle(`width`,n.width+`px`),this.setElementStyle(`height`,n.height+`px`)),t}},m=n(Glyph);export{m as t};
|
|
2
|
+
//# sourceMappingURL=Glyph-wN7bk7mg.js.map
|