@tcn/ui 0.12.4 → 0.12.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/dist/overlay/frame/frame.d.ts.map +1 -1
  2. package/dist/overlay/frame/frame.js +57 -63
  3. package/dist/overlay/frame/frame.js.map +1 -1
  4. package/dist/stacks/box/box.d.ts +5 -4
  5. package/dist/stacks/box/box.d.ts.map +1 -1
  6. package/dist/stacks/box/box.js.map +1 -1
  7. package/dist/stacks/box/detect_resize_bounds.d.ts +15 -0
  8. package/dist/stacks/box/detect_resize_bounds.d.ts.map +1 -0
  9. package/dist/stacks/box/detect_resize_bounds.js +49 -0
  10. package/dist/stacks/box/detect_resize_bounds.js.map +1 -0
  11. package/dist/stacks/box/resize_handlers.d.ts.map +1 -1
  12. package/dist/stacks/box/resize_handlers.js +51 -44
  13. package/dist/stacks/box/resize_handlers.js.map +1 -1
  14. package/dist/stacks/box/start_resize_handle.d.ts.map +1 -1
  15. package/dist/stacks/box/start_resize_handle.js +2 -1
  16. package/dist/stacks/box/start_resize_handle.js.map +1 -1
  17. package/dist/stacks/box/types.d.ts +17 -4
  18. package/dist/stacks/box/types.d.ts.map +1 -1
  19. package/dist/surfaces/modal/modal.d.ts.map +1 -1
  20. package/dist/surfaces/modal/modal.js +22 -13
  21. package/dist/surfaces/modal/modal.js.map +1 -1
  22. package/dist/surfaces/window/window.d.ts.map +1 -1
  23. package/dist/surfaces/window/window.js +21 -24
  24. package/dist/surfaces/window/window.js.map +1 -1
  25. package/package.json +2 -2
  26. package/src/overlay/frame/frame.tsx +34 -51
  27. package/src/stacks/box/box.tsx +10 -16
  28. package/src/stacks/box/detect_resize_bounds.ts +84 -0
  29. package/src/stacks/box/resize_handlers.ts +27 -15
  30. package/src/stacks/box/start_resize_handle.tsx +6 -3
  31. package/src/stacks/box/types.ts +23 -25
  32. package/src/surfaces/modal/__stories__/modal.stories.tsx +70 -3
  33. package/src/surfaces/modal/modal.tsx +11 -2
  34. package/src/surfaces/window/window.stories.tsx +64 -8
  35. package/src/surfaces/window/window.tsx +6 -9
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/stacks/box/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,OAAO,CAAC;AACjD,MAAM,MAAM,kBAAkB,GAAG,KAAK,GAAG,QAAQ,CAAC;AAElD,MAAM,MAAM,aAAa,GAAG,CAE1B,KAAK,EAAE,MAAM,EAEb,MAAM,EAAE,iBAAiB,EAEzB,UAAU,EAAE,MAAM,EAElB,YAAY,EAAE,MAAM,EAEpB,OAAO,EAAE,OAAO,KACb,IAAI,CAAC;AAEV,MAAM,MAAM,cAAc,GAAG,CAE3B,MAAM,EAAE,MAAM,EAEd,MAAM,EAAE,kBAAkB,EAE1B,UAAU,EAAE,MAAM,EAElB,YAAY,EAAE,MAAM,EAEpB,OAAO,EAAE,OAAO,KACb,IAAI,CAAC;AAEV,MAAM,WAAW,2BAA2B;IAC1C,SAAS,EAAE,KAAK,CAAC,gBAAgB,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IACtD,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,iBAAiB,KAAK,IAAI,CAAC;CACvE;AAED,MAAM,WAAW,yBAAyB;IACxC,SAAS,EAAE,KAAK,CAAC,gBAAgB,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IACtD,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,iBAAiB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,kBAAkB,KAAK,IAAI,CAAC;CAC1E"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/stacks/box/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,OAAO,CAAC;AACjD,MAAM,MAAM,kBAAkB,GAAG,KAAK,GAAG,QAAQ,CAAC;AAElD,MAAM,WAAW,mBAAmB,CAClC,MAAM,SAAS,iBAAiB,GAAG,kBAAkB;IAErD,MAAM,EAAE,MAAM,CAAC;IAEf,UAAU,EAAE,MAAM,CAAC;IAEnB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,oBAAqB,SAAQ,mBAAmB,CAAC,iBAAiB,CAAC;IAClF,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,qBAAsB,SAAQ,mBAAmB,CAAC,kBAAkB,CAAC;IACpF,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,gBAAgB,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,iBAAiB,KAAK,IAAI,CAAC;AAClF,MAAM,MAAM,iBAAiB,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,kBAAkB,KAAK,IAAI,CAAC;AAErF,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,EAAE,oBAAoB,KAAK,IAAI,CAAC;AACpE,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,EAAE,qBAAqB,KAAK,IAAI,CAAC;AAEtE,MAAM,WAAW,2BAA2B;IAC1C,SAAS,EAAE,KAAK,CAAC,gBAAgB,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IACtD,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;CACrC;AAED,MAAM,WAAW,yBAAyB;IACxC,SAAS,EAAE,KAAK,CAAC,gBAAgB,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IACtD,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;CACvC"}
@@ -1 +1 @@
1
- {"version":3,"file":"modal.d.ts","sourceRoot":"","sources":["../../../src/surfaces/modal/modal.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAS,KAAK,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAMtE,MAAM,MAAM,UAAU,GAAG,UAAU,CAAC;AAEpC,eAAO,MAAM,KAAK,+QAkBhB,CAAC"}
1
+ {"version":3,"file":"modal.d.ts","sourceRoot":"","sources":["../../../src/surfaces/modal/modal.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAS,KAAK,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAMtE,MAAM,MAAM,UAAU,GAAG,UAAU,CAAC;AAEpC,eAAO,MAAM,KAAK,+QA2BhB,CAAC"}
@@ -1,23 +1,32 @@
1
1
  import { jsx as o } from "react/jsx-runtime";
2
- import { clsx as e } from "clsx";
3
- import s from "react";
4
- import { Frame as d } from "../../overlay/frame/frame.js";
5
- import { Scaffold as n } from "../../layouts/scaffold/scaffold.js";
6
- import '../../modal.css';const i = "_modal_473c6ef", p = { modal: i }, N = s.forwardRef(function({ children: t, className: a, isOpen: r, draggable: m = !1, veil: c = !0, ...f }, l) {
2
+ import { clsx as s } from "clsx";
3
+ import d from "react";
4
+ import { Frame as n } from "../../overlay/frame/frame.js";
5
+ import { Scaffold as i } from "../../layouts/scaffold/scaffold.js";
6
+ import '../../modal.css';const p = "_modal_473c6ef", u = { modal: p }, R = d.forwardRef(function({
7
+ children: a,
8
+ className: t,
9
+ isOpen: r,
10
+ veil: m = !0,
11
+ resizable: f = !1,
12
+ draggable: l = !1,
13
+ ...c
14
+ }, e) {
7
15
  return /* @__PURE__ */ o(
8
- d,
16
+ n,
9
17
  {
10
- ref: l,
18
+ ref: e,
11
19
  isOpen: r,
12
- draggable: m,
13
- veil: c,
14
- className: e(p.modal, "tcn-surface", "tcn-modal", a),
15
- ...f,
16
- children: /* @__PURE__ */ o(n, { className: "tcn-modal-scaffold", width: "100%", height: "100%", children: t })
20
+ veil: m,
21
+ draggable: l,
22
+ resizable: f,
23
+ className: s(u.modal, "tcn-surface", "tcn-modal", t),
24
+ ...c,
25
+ children: /* @__PURE__ */ o(i, { className: "tcn-modal-scaffold", width: "100%", height: "100%", children: a })
17
26
  }
18
27
  );
19
28
  });
20
29
  export {
21
- N as Modal
30
+ R as Modal
22
31
  };
23
32
  //# sourceMappingURL=modal.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"modal.js","sources":["../../../src/surfaces/modal/modal.tsx"],"sourcesContent":["import { clsx } from 'clsx';\nimport React from 'react';\nimport { Frame, type FrameProps } from '../../overlay/frame/frame.js';\nimport { Scaffold } from '../../layouts/scaffold/scaffold.js';\n\n// Styles\nimport styles from './modal.module.css';\n\nexport type ModalProps = FrameProps;\n\nexport const Modal = React.forwardRef<HTMLElement, ModalProps>(function Modal(\n { children, className, isOpen, draggable = false, veil = true, ...props }: ModalProps,\n ref\n) {\n return (\n <Frame\n ref={ref}\n isOpen={isOpen}\n draggable={draggable}\n veil={veil}\n className={clsx(styles['modal'], 'tcn-surface', 'tcn-modal', className)}\n {...props}\n >\n <Scaffold className={'tcn-modal-scaffold'} width=\"100%\" height=\"100%\">\n {children}\n </Scaffold>\n </Frame>\n );\n});\n"],"names":["Modal","React","children","className","isOpen","draggable","veil","props","ref","jsx","Frame","clsx","styles","Scaffold"],"mappings":";;;;;8CAUaA,IAAQC,EAAM,WAAoC,SAC7D,EAAE,UAAAC,GAAU,WAAAC,GAAW,QAAAC,GAAQ,WAAAC,IAAY,IAAO,MAAAC,IAAO,IAAM,GAAGC,EAAA,GAClEC,GACA;AACA,SACE,gBAAAC;AAAA,IAACC;AAAA,IAAA;AAAA,MACC,KAAAF;AAAA,MACA,QAAAJ;AAAA,MACA,WAAAC;AAAA,MACA,MAAAC;AAAA,MACA,WAAWK,EAAKC,EAAO,OAAU,eAAe,aAAaT,CAAS;AAAA,MACrE,GAAGI;AAAA,MAEJ,UAAA,gBAAAE,EAACI,KAAS,WAAW,sBAAsB,OAAM,QAAO,QAAO,QAC5D,UAAAX,EAAA,CACH;AAAA,IAAA;AAAA,EAAA;AAGN,CAAC;"}
1
+ {"version":3,"file":"modal.js","sources":["../../../src/surfaces/modal/modal.tsx"],"sourcesContent":["import { clsx } from 'clsx';\nimport React from 'react';\nimport { Frame, type FrameProps } from '../../overlay/frame/frame.js';\nimport { Scaffold } from '../../layouts/scaffold/scaffold.js';\n\n// Styles\nimport styles from './modal.module.css';\n\nexport type ModalProps = FrameProps;\n\nexport const Modal = React.forwardRef<HTMLElement, ModalProps>(function Modal(\n {\n children,\n className,\n isOpen,\n veil = true,\n resizable = false,\n draggable = false,\n ...props\n }: ModalProps,\n ref\n) {\n return (\n <Frame\n ref={ref}\n isOpen={isOpen}\n veil={veil}\n draggable={draggable}\n resizable={resizable}\n className={clsx(styles['modal'], 'tcn-surface', 'tcn-modal', className)}\n {...props}\n >\n <Scaffold className={'tcn-modal-scaffold'} width=\"100%\" height=\"100%\">\n {children}\n </Scaffold>\n </Frame>\n );\n});\n"],"names":["Modal","React","children","className","isOpen","veil","resizable","draggable","props","ref","jsx","Frame","clsx","styles","Scaffold"],"mappings":";;;;;8CAUaA,IAAQC,EAAM,WAAoC,SAC7D;AAAA,EACE,UAAAC;AAAA,EACA,WAAAC;AAAA,EACA,QAAAC;AAAA,EACA,MAAAC,IAAO;AAAA,EACP,WAAAC,IAAY;AAAA,EACZ,WAAAC,IAAY;AAAA,EACZ,GAAGC;AACL,GACAC,GACA;AACA,SACE,gBAAAC;AAAA,IAACC;AAAA,IAAA;AAAA,MACC,KAAAF;AAAA,MACA,QAAAL;AAAA,MACA,MAAAC;AAAA,MACA,WAAAE;AAAA,MACA,WAAAD;AAAA,MACA,WAAWM,EAAKC,EAAO,OAAU,eAAe,aAAaV,CAAS;AAAA,MACrE,GAAGK;AAAA,MAEJ,UAAA,gBAAAE,EAACI,KAAS,WAAW,sBAAsB,OAAM,QAAO,QAAO,QAC5D,UAAAZ,EAAA,CACH;AAAA,IAAA;AAAA,EAAA;AAGN,CAAC;"}
@@ -1 +1 @@
1
- {"version":3,"file":"window.d.ts","sourceRoot":"","sources":["../../../src/surfaces/window/window.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAS,KAAK,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAMtE,MAAM,MAAM,WAAW,GAAG,UAAU,CAAC;AAErC,eAAO,MAAM,MAAM,+QA8BjB,CAAC"}
1
+ {"version":3,"file":"window.d.ts","sourceRoot":"","sources":["../../../src/surfaces/window/window.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAS,KAAK,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAMtE,MAAM,MAAM,WAAW,GAAG,UAAU,CAAC;AAErC,eAAO,MAAM,MAAM,+QA2BjB,CAAC"}
@@ -1,35 +1,32 @@
1
1
  import { jsx as o } from "react/jsx-runtime";
2
- import { clsx as w } from "clsx";
3
- import a from "react";
4
- import { Frame as m } from "../../overlay/frame/frame.js";
5
- import { Scaffold as l } from "../../layouts/scaffold/scaffold.js";
6
- import '../../window.css';const p = "_window_7610fdb", u = { window: p }, g = a.forwardRef(function({
7
- children: r,
8
- className: t,
9
- isOpen: e,
10
- draggable: i = !0,
11
- resizable: _ = !0,
2
+ import { clsx as d } from "clsx";
3
+ import w from "react";
4
+ import { Frame as a } from "../../overlay/frame/frame.js";
5
+ import { Scaffold as m } from "../../layouts/scaffold/scaffold.js";
6
+ import '../../window.css';const l = "_window_7610fdb", p = { window: l }, W = w.forwardRef(function({
7
+ children: t,
8
+ className: r,
9
+ isOpen: f,
12
10
  veil: n = !1,
13
- width: f,
14
- height: c,
15
- ...s
16
- }, d) {
11
+ draggable: i = !0,
12
+ resizable: c = !1,
13
+ ...e
14
+ }, s) {
17
15
  return /* @__PURE__ */ o(
18
- m,
16
+ a,
19
17
  {
20
- isOpen: e,
21
- draggable: i,
18
+ ref: s,
19
+ isOpen: f,
22
20
  veil: n,
23
- className: w(u.window, "tcn-surface", "tcn-window", t),
24
- width: f,
25
- height: c,
26
- ref: d,
27
- ...s,
28
- children: /* @__PURE__ */ o(l, { width: "100%", height: "100%", className: "tcn-window-scaffold", children: r })
21
+ draggable: i,
22
+ resizable: c,
23
+ className: d(p.window, "tcn-surface", "tcn-window", r),
24
+ ...e,
25
+ children: /* @__PURE__ */ o(m, { className: "tcn-window-scaffold", width: "100%", height: "100%", children: t })
29
26
  }
30
27
  );
31
28
  });
32
29
  export {
33
- g as Window
30
+ W as Window
34
31
  };
35
32
  //# sourceMappingURL=window.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"window.js","sources":["../../../src/surfaces/window/window.tsx"],"sourcesContent":["import { clsx } from 'clsx';\nimport React from 'react';\nimport { Frame, type FrameProps } from '../../overlay/frame/frame.js';\nimport { Scaffold } from '../../layouts/scaffold/scaffold.js';\n\n// Styles\nimport styles from './window.module.css';\n\nexport type WindowProps = FrameProps;\n\nexport const Window = React.forwardRef<HTMLElement, WindowProps>(function Window(\n {\n children,\n className,\n isOpen,\n draggable = true,\n resizable = true,\n veil = false,\n width,\n height,\n ...props\n }: WindowProps,\n ref\n) {\n return (\n <Frame\n isOpen={isOpen}\n draggable={draggable}\n veil={veil}\n className={clsx(styles['window'], 'tcn-surface', 'tcn-window', className)}\n width={width}\n height={height}\n ref={ref}\n {...props}\n >\n <Scaffold width=\"100%\" height=\"100%\" className={'tcn-window-scaffold'}>\n {children}\n </Scaffold>\n </Frame>\n );\n});\n"],"names":["Window","React","children","className","isOpen","draggable","resizable","veil","width","height","props","ref","jsx","Frame","clsx","styles","Scaffold"],"mappings":";;;;;gDAUaA,IAASC,EAAM,WAAqC,SAC/D;AAAA,EACE,UAAAC;AAAA,EACA,WAAAC;AAAA,EACA,QAAAC;AAAA,EACA,WAAAC,IAAY;AAAA,EACZ,WAAAC,IAAY;AAAA,EACZ,MAAAC,IAAO;AAAA,EACP,OAAAC;AAAA,EACA,QAAAC;AAAA,EACA,GAAGC;AACL,GACAC,GACA;AACA,SACE,gBAAAC;AAAA,IAACC;AAAA,IAAA;AAAA,MACC,QAAAT;AAAA,MACA,WAAAC;AAAA,MACA,MAAAE;AAAA,MACA,WAAWO,EAAKC,EAAO,QAAW,eAAe,cAAcZ,CAAS;AAAA,MACxE,OAAAK;AAAA,MACA,QAAAC;AAAA,MACA,KAAAE;AAAA,MACC,GAAGD;AAAA,MAEJ,UAAA,gBAAAE,EAACI,KAAS,OAAM,QAAO,QAAO,QAAO,WAAW,uBAC7C,UAAAd,EAAA,CACH;AAAA,IAAA;AAAA,EAAA;AAGN,CAAC;"}
1
+ {"version":3,"file":"window.js","sources":["../../../src/surfaces/window/window.tsx"],"sourcesContent":["import { clsx } from 'clsx';\nimport React from 'react';\nimport { Frame, type FrameProps } from '../../overlay/frame/frame.js';\nimport { Scaffold } from '../../layouts/scaffold/scaffold.js';\n\n// Styles\nimport styles from './window.module.css';\n\nexport type WindowProps = FrameProps;\n\nexport const Window = React.forwardRef<HTMLElement, WindowProps>(function Window(\n {\n children,\n className,\n isOpen,\n veil = false,\n draggable = true,\n resizable = false,\n ...props\n }: WindowProps,\n ref\n) {\n return (\n <Frame\n ref={ref}\n isOpen={isOpen}\n veil={veil}\n draggable={draggable}\n resizable={resizable}\n className={clsx(styles['window'], 'tcn-surface', 'tcn-window', className)}\n {...props}\n >\n <Scaffold className={'tcn-window-scaffold'} width=\"100%\" height=\"100%\">\n {children}\n </Scaffold>\n </Frame>\n );\n});\n"],"names":["Window","React","children","className","isOpen","veil","draggable","resizable","props","ref","jsx","Frame","clsx","styles","Scaffold"],"mappings":";;;;;gDAUaA,IAASC,EAAM,WAAqC,SAC/D;AAAA,EACE,UAAAC;AAAA,EACA,WAAAC;AAAA,EACA,QAAAC;AAAA,EACA,MAAAC,IAAO;AAAA,EACP,WAAAC,IAAY;AAAA,EACZ,WAAAC,IAAY;AAAA,EACZ,GAAGC;AACL,GACAC,GACA;AACA,SACE,gBAAAC;AAAA,IAACC;AAAA,IAAA;AAAA,MACC,KAAAF;AAAA,MACA,QAAAL;AAAA,MACA,MAAAC;AAAA,MACA,WAAAC;AAAA,MACA,WAAAC;AAAA,MACA,WAAWK,EAAKC,EAAO,QAAW,eAAe,cAAcV,CAAS;AAAA,MACvE,GAAGK;AAAA,MAEJ,UAAA,gBAAAE,EAACI,KAAS,WAAW,uBAAuB,OAAM,QAAO,QAAO,QAC7D,UAAAZ,EAAA,CACH;AAAA,IAAA;AAAA,EAAA;AAGN,CAAC;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tcn/ui",
3
- "version": "0.12.4",
3
+ "version": "0.12.5",
4
4
  "type": "module",
5
5
  "description": "",
6
6
  "author": "TCN",
@@ -144,7 +144,7 @@
144
144
  "react-color": "^2.19.3",
145
145
  "react-phone-number-input": "^3.4.16",
146
146
  "@tcn/icons": "2.3.0",
147
- "@tcn/state": "1.2.1"
147
+ "@tcn/state": "1.3.0"
148
148
  },
149
149
  "scripts": {
150
150
  "build": "vite build",
@@ -1,7 +1,13 @@
1
1
  import { clsx } from 'clsx';
2
2
  import React, { useCallback } from 'react';
3
3
  import { flushSync } from 'react-dom';
4
- import { Box, ZStack, type BoxProps } from '../../stacks/index.js';
4
+ import {
5
+ Box,
6
+ ZStack,
7
+ type BoxProps,
8
+ type OnHeightResizePayload,
9
+ type OnWidthResizePayload,
10
+ } from '../../stacks/index.js';
5
11
  import { useDragContainer } from '../../utils/dnd/context.js';
6
12
  import { Draggable } from '../../utils/dnd/draggable/draggable.js';
7
13
  import { Portal } from '../portal/portal.js';
@@ -48,6 +54,10 @@ export const Frame = React.forwardRef<HTMLElement, FrameProps>(function Frame(
48
54
  enableResizeOnRight={resizable}
49
55
  enableResizeOnTop={resizable}
50
56
  enableResizeOnBottom={resizable}
57
+ // TODO: check to see if these should be enabled, and if so - if left/right should be disabled.
58
+ // Could add a "directional" prop and use that in conjunction with enableResizeOnStart/End and deprecate enableResizeOnLeft/Right.
59
+ // enableResizeOnStart={resizable}
60
+ // enableResizeOnEnd={resizable}
51
61
  draggable={draggable}
52
62
  {...rest}
53
63
  >
@@ -77,64 +87,37 @@ export const FrameDialog = React.forwardRef<HTMLElement, FrameDialogProps>(
77
87
  const drag = useDragContainer();
78
88
 
79
89
  const handleWidthResize = React.useCallback(
80
- (
81
- width: number,
82
- origin: 'left' | 'right',
83
- totalDelta: number,
84
- currentDelta: number,
85
- atLimit: boolean
86
- ) => {
90
+ (payload: OnWidthResizePayload) => {
87
91
  if (!draggable) return;
88
- if (atLimit) return;
89
- if (origin === 'right') {
90
- flushSync(() => {
91
- drag.setPosition(prev => ({
92
- x: prev.x + currentDelta / 2,
93
- y: prev.y,
94
- }));
95
- });
96
- }
97
- if (origin === 'left') {
98
- flushSync(() => {
99
- drag.setPosition(prev => ({
100
- x: prev.x - currentDelta / 2,
101
- y: prev.y,
102
- }));
103
- });
104
- }
92
+ if (payload.currentDelta === 0) return;
93
+ const sign = payload.origin === 'right' ? 1 : -1;
94
+ const dx = (payload.currentDelta / 2) * sign;
95
+ flushSync(() => {
96
+ drag.setPosition(prev => ({
97
+ x: prev.x + dx,
98
+ y: prev.y,
99
+ }));
100
+ });
105
101
 
106
- onWidthResize?.(width, origin, totalDelta, currentDelta, atLimit);
102
+ onWidthResize?.(payload);
107
103
  },
108
104
  [onWidthResize, drag, draggable]
109
105
  );
110
106
 
111
107
  const handleHeightResize = useCallback(
112
- (
113
- height: number,
114
- origin: 'top' | 'bottom',
115
- totalDelta: number,
116
- currentDelta: number,
117
- atLimit: boolean
118
- ) => {
108
+ (payload: OnHeightResizePayload) => {
119
109
  if (!draggable) return;
120
- if (atLimit) return;
121
- if (origin === 'bottom') {
122
- flushSync(() => {
123
- drag.setPosition(prev => ({
124
- x: prev.x,
125
- y: prev.y + currentDelta / 2,
126
- }));
127
- });
128
- }
129
- if (origin === 'top') {
130
- flushSync(() => {
131
- drag.setPosition(prev => ({
132
- x: prev.x,
133
- y: prev.y - currentDelta / 2,
134
- }));
135
- });
136
- }
137
- onHeightResize?.(height, origin, totalDelta, currentDelta, atLimit);
110
+ if (payload.currentDelta === 0) return;
111
+ const sign = payload.origin === 'bottom' ? 1 : -1;
112
+ const half = payload.currentDelta / 2;
113
+ const dy = half * sign;
114
+ flushSync(() => {
115
+ drag.setPosition(prev => ({
116
+ x: prev.x,
117
+ y: prev.y + dy,
118
+ }));
119
+ });
120
+ onHeightResize?.(payload);
138
121
  },
139
122
  [onHeightResize, drag, draggable]
140
123
  );
@@ -11,6 +11,12 @@ import { LeftResizeHandle } from './left_resize_handle.js';
11
11
  import { RightResizeHandle } from './right_resize_handle.js';
12
12
  import { StartResizeHandle } from './start_resize_handle.js';
13
13
  import { TopResizeHandle } from './top_resize_handle.js';
14
+ import type {
15
+ OnHeightResize,
16
+ OnHeightResizeEnd,
17
+ OnWidthResize,
18
+ OnWidthResizeEnd,
19
+ } from './types.js';
14
20
 
15
21
  export interface BoxProps<T extends HTMLElement = HTMLElement> extends HTMLAttributes<T> {
16
22
  as?: string;
@@ -45,22 +51,10 @@ export interface BoxProps<T extends HTMLElement = HTMLElement> extends HTMLAttri
45
51
  enableResizeOnRight?: boolean;
46
52
  horizontalHandleProps?: HandleProps;
47
53
  verticalHandleProps?: HandleProps;
48
- onWidthResize?: (
49
- width: number,
50
- origin: 'left' | 'right',
51
- totalDelta: number,
52
- currentDelta: number,
53
- atLimit: boolean
54
- ) => void;
55
- onHeightResize?: (
56
- height: number,
57
- origin: 'top' | 'bottom',
58
- totalDelta: number,
59
- currentDelta: number,
60
- atLimit: boolean
61
- ) => void;
62
- onWidthResizeEnd?: (width: number, origin: 'left' | 'right') => void;
63
- onHeightResizeEnd?: (height: number, origin: 'top' | 'bottom') => void;
54
+ onWidthResize?: OnWidthResize;
55
+ onHeightResize?: OnHeightResize;
56
+ onWidthResizeEnd?: OnWidthResizeEnd;
57
+ onHeightResizeEnd?: OnHeightResizeEnd;
64
58
  }
65
59
 
66
60
  export const Box = React.forwardRef<HTMLElement, BoxProps>(function Box(
@@ -0,0 +1,84 @@
1
+ type ConstraintAxis = 'width' | 'height';
2
+
3
+ export type DetectResizeBoundsParams = {
4
+ element: HTMLElement;
5
+ axis: ConstraintAxis;
6
+ nextSize: number;
7
+ epsilon?: number; // Tolerance for the constraint hit detection.
8
+ };
9
+
10
+ export type DetectResizeBoundsResult = {
11
+ hitMin: boolean;
12
+ hitMax: boolean;
13
+ clamped: boolean;
14
+ };
15
+
16
+ const styleKeys = {
17
+ width: {
18
+ size: 'width',
19
+ min: 'minWidth',
20
+ max: 'maxWidth',
21
+ },
22
+ height: {
23
+ size: 'height',
24
+ min: 'minHeight',
25
+ max: 'maxHeight',
26
+ },
27
+ } as const;
28
+
29
+ function parsePx(value: string): number | null {
30
+ const match = /^(-?\d+(?:\.\d+)?)px$/.exec(value.trim());
31
+ return match ? Number(match[1]) : null;
32
+ }
33
+
34
+ function detectByPixelValue(nextSize: number, min: string, max: string) {
35
+ const minPx = parsePx(min);
36
+ const maxPx = parsePx(max);
37
+ const hitMin = minPx !== null && nextSize < minPx;
38
+ const hitMax = maxPx !== null && nextSize > maxPx;
39
+ return {
40
+ hitMin,
41
+ hitMax,
42
+ clamped: hitMin || hitMax,
43
+ };
44
+ }
45
+
46
+ export function detectResizeBounds({
47
+ element,
48
+ axis,
49
+ nextSize,
50
+ epsilon = 0.5,
51
+ }: DetectResizeBoundsParams): DetectResizeBoundsResult {
52
+ const keys = styleKeys[axis];
53
+
54
+ const computed = getComputedStyle(element);
55
+ const fastPath = detectByPixelValue(nextSize, computed[keys.min], computed[keys.max]);
56
+ if (fastPath.clamped) return fastPath;
57
+
58
+ const style = element.style;
59
+ const prevInlineSize = style[keys.size]; // Save the previous size to revert later.
60
+
61
+ try {
62
+ // Temporarily apply the new size to the element to offload bound test to browser.
63
+ style[keys.size] = `${nextSize}px`;
64
+
65
+ // Force layout so browser resolves min/max/intrinsic constraints.
66
+ const rect = element.getBoundingClientRect();
67
+ const renderedSize = rect[keys.size];
68
+
69
+ const delta = renderedSize - nextSize;
70
+
71
+ const hitMin = delta > epsilon;
72
+ const hitMax = delta < -epsilon;
73
+ const clamped = hitMin || hitMax;
74
+
75
+ return {
76
+ hitMin,
77
+ hitMax,
78
+ clamped,
79
+ };
80
+ } finally {
81
+ // revert the style change
82
+ style[keys.size] = prevInlineSize;
83
+ }
84
+ }
@@ -4,6 +4,7 @@ import {
4
4
  type OnHeightResize,
5
5
  type WidthResizeOrigin,
6
6
  } from './types';
7
+ import { detectResizeBounds } from './detect_resize_bounds.js';
7
8
 
8
9
  function createVeil() {
9
10
  const veil = window.document.createElement('div');
@@ -25,9 +26,7 @@ export function createHorizontalResizeHandler(
25
26
  return function startHorizontalResize(event: React.MouseEvent) {
26
27
  const box = targetRef.current;
27
28
 
28
- if (box == null) {
29
- return;
30
- }
29
+ if (box == null) return;
31
30
 
32
31
  const veil = createVeil();
33
32
  box.appendChild(veil);
@@ -42,18 +41,24 @@ export function createHorizontalResizeHandler(
42
41
  let width = startRect.width;
43
42
 
44
43
  const drag = (event: MouseEvent) => {
45
- const beforeWidth = box.getBoundingClientRect().width;
46
44
  const totalDelta = direction * (event.clientX - startX);
47
45
  const newWidth = startRect.width + totalDelta;
46
+
47
+ const result = detectResizeBounds({
48
+ element: box,
49
+ axis: 'width',
50
+ nextSize: newWidth,
51
+ });
52
+
53
+ if (result.clamped) return;
54
+
48
55
  const currentDelta = newWidth - width;
49
56
 
57
+ // apply the new width
50
58
  width = newWidth;
51
-
52
59
  box.style.width = `${newWidth}px`;
53
60
 
54
- const afterWidth = box.getBoundingClientRect().width;
55
- const atLimit = afterWidth === beforeWidth;
56
- onWidthResize?.(newWidth, origin, totalDelta, currentDelta, atLimit);
61
+ onWidthResize?.({ width: newWidth, origin, totalDelta, currentDelta });
57
62
  event.stopPropagation();
58
63
  event.preventDefault();
59
64
  };
@@ -95,9 +100,7 @@ export function createVerticalResizeHandler(
95
100
  return function startVerticalResize(event: React.MouseEvent) {
96
101
  const box = targetRef.current;
97
102
 
98
- if (box == null) {
99
- return;
100
- }
103
+ if (box == null) return;
101
104
 
102
105
  const veil = createVeil();
103
106
  box.appendChild(veil);
@@ -107,15 +110,24 @@ export function createVerticalResizeHandler(
107
110
  let height = startRect.height;
108
111
 
109
112
  const drag = (event: MouseEvent) => {
110
- const beforeHeight = box.getBoundingClientRect().height;
111
113
  const totalDelta = direction * (event.clientY - startY);
112
114
  const newHeight = startRect.height + totalDelta;
115
+
116
+ const result = detectResizeBounds({
117
+ element: box,
118
+ axis: 'height',
119
+ nextSize: newHeight,
120
+ });
121
+
122
+ if (result.clamped) return;
123
+
113
124
  const currentDelta = newHeight - height;
125
+
126
+ // apply the new height
114
127
  height = newHeight;
115
128
  box.style.height = `${newHeight}px`;
116
- const afterHeight = box.getBoundingClientRect().height;
117
- const atLimit = afterHeight === beforeHeight;
118
- onHeightResize?.(newHeight, origin, totalDelta, currentDelta, atLimit);
129
+
130
+ onHeightResize?.({ height: newHeight, origin, totalDelta, currentDelta });
119
131
  event.stopPropagation();
120
132
  event.preventDefault();
121
133
  };
@@ -2,6 +2,7 @@ import { clsx } from 'clsx';
2
2
  import { createHorizontalResizeHandler } from './resize_handlers.js';
3
3
  import styles from './start_resize_handle.module.css';
4
4
  import type { HorizontalResizeHandleProps } from './types.js';
5
+ import { CSSProperties } from 'react';
5
6
 
6
7
  export type StartResizeHandleProps = HorizontalResizeHandleProps;
7
8
 
@@ -15,15 +16,17 @@ export function StartResizeHandle({
15
16
  targetRef,
16
17
  onWidthResize,
17
18
  onWidthResizeEnd,
18
- 'left'
19
+ 'left',
20
+ true
19
21
  );
22
+
20
23
  const offset = handleProps?.offset ? handleProps.offset : -8;
21
24
 
22
- const startResizeHandleStyle: any = {
25
+ const startResizeHandleStyle = {
23
26
  ...handleProps?.style,
24
27
  '--resize-offset': `${offset}px`,
25
28
  width: handleProps?.size || '16px',
26
- };
29
+ } as CSSProperties;
27
30
 
28
31
  return (
29
32
  <div
@@ -3,42 +3,40 @@ import type { HandleProps } from './handle_props.js';
3
3
  export type WidthResizeOrigin = 'left' | 'right';
4
4
  export type HeightResizeOrigin = 'top' | 'bottom';
5
5
 
6
- export type OnWidthResize = (
7
- // Newly calculated width
8
- width: number,
9
- // Origin of the resize - left or right of the box
10
- origin: WidthResizeOrigin,
6
+ export interface BaseOnResizePayload<
7
+ Origin extends WidthResizeOrigin | HeightResizeOrigin,
8
+ > {
9
+ origin: Origin;
11
10
  // Total delta of the resize (the sum of all deltas before end event)
12
- totalDelta: number,
11
+ totalDelta: number;
13
12
  // Current delta of the resize (the delta of the current event)
14
- currentDelta: number,
15
- // Whether the resize is at the limit of the box, this includes min-content, max-content, and min-width/height
16
- atLimit: boolean
17
- ) => void;
18
-
19
- export type OnHeightResize = (
20
- // Newly calculated height
21
- height: number,
22
- // Origin of the resize - top or bottom of the box
23
- origin: HeightResizeOrigin,
24
- // Total delta of the resize (the sum of all deltas before end event)
25
- totalDelta: number,
26
- // Current delta of the resize (the delta of the current event)
27
- currentDelta: number,
28
- // Whether the resize is at the limit of the box, this includes min-content, max-content, and min-width/height
29
- atLimit: boolean
30
- ) => void;
13
+ currentDelta: number;
14
+ }
15
+
16
+ export interface OnWidthResizePayload extends BaseOnResizePayload<WidthResizeOrigin> {
17
+ width: number;
18
+ }
19
+
20
+ export interface OnHeightResizePayload extends BaseOnResizePayload<HeightResizeOrigin> {
21
+ height: number;
22
+ }
23
+
24
+ export type OnWidthResizeEnd = (width: number, origin: WidthResizeOrigin) => void;
25
+ export type OnHeightResizeEnd = (height: number, origin: HeightResizeOrigin) => void;
26
+
27
+ export type OnWidthResize = (payload: OnWidthResizePayload) => void;
28
+ export type OnHeightResize = (payload: OnHeightResizePayload) => void;
31
29
 
32
30
  export interface HorizontalResizeHandleProps {
33
31
  targetRef: React.MutableRefObject<HTMLElement | null>;
34
32
  handleProps?: HandleProps;
35
33
  onWidthResize?: OnWidthResize;
36
- onWidthResizeEnd?: (width: number, origin: WidthResizeOrigin) => void;
34
+ onWidthResizeEnd?: OnWidthResizeEnd;
37
35
  }
38
36
 
39
37
  export interface VerticalResizeHandleProps {
40
38
  targetRef: React.MutableRefObject<HTMLElement | null>;
41
39
  handleProps?: HandleProps;
42
40
  onHeightResize?: OnHeightResize;
43
- onHeightResizeEnd?: (height: number, origin: HeightResizeOrigin) => void;
41
+ onHeightResizeEnd?: OnHeightResizeEnd;
44
42
  }