@tcn/ui 0.16.0 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/card.css +1 -0
- package/dist/column.css +1 -1
- package/dist/containers.css +1 -1
- package/dist/containers.module-BmICKsOK.js +5 -0
- package/dist/containers.module-BmICKsOK.js.map +1 -0
- package/dist/form/field/field.js +11 -8
- package/dist/form/field/field.js.map +1 -1
- package/dist/inputs/color_input/color_picker.js +5 -2
- package/dist/inputs/color_input/color_picker.js.map +1 -1
- package/dist/inputs/combo_box/combo_box.js +18 -15
- package/dist/inputs/combo_box/combo_box.js.map +1 -1
- package/dist/inputs/date_picker/date_picker.js +13 -10
- package/dist/inputs/date_picker/date_picker.js.map +1 -1
- package/dist/inputs/date_picker/date_picker_input.js +20 -17
- package/dist/inputs/date_picker/date_picker_input.js.map +1 -1
- package/dist/inputs/date_picker/date_picker_year_selector.js +5 -2
- package/dist/inputs/date_picker/date_picker_year_selector.js.map +1 -1
- package/dist/inputs/mask_input/key_capture_input.js +26 -23
- package/dist/inputs/mask_input/key_capture_input.js.map +1 -1
- package/dist/inputs/mask_input/mask_input.js +5 -2
- package/dist/inputs/mask_input/mask_input.js.map +1 -1
- package/dist/inputs/multiselect/multiselect.js +22 -19
- package/dist/inputs/multiselect/multiselect.js.map +1 -1
- package/dist/inputs/phone_number_input/phone_number_context.js +7 -4
- package/dist/inputs/phone_number_input/phone_number_context.js.map +1 -1
- package/dist/inputs/select/select.js +5 -2
- package/dist/inputs/select/select.js.map +1 -1
- package/dist/inputs/slider/slider.js +19 -16
- package/dist/inputs/slider/slider.js.map +1 -1
- package/dist/inputs/suggestions/suggestion_list.js +5 -2
- package/dist/inputs/suggestions/suggestion_list.js.map +1 -1
- package/dist/inputs/switch/switch.js +18 -15
- package/dist/inputs/switch/switch.js.map +1 -1
- package/dist/inputs/unit_input/unit_input.js +15 -12
- package/dist/inputs/unit_input/unit_input.js.map +1 -1
- package/dist/layouts/containers/columns/columns.d.ts +6 -1
- package/dist/layouts/containers/columns/columns.d.ts.map +1 -1
- package/dist/layouts/containers/columns/columns.js +30 -7
- package/dist/layouts/containers/columns/columns.js.map +1 -1
- package/dist/layouts/containers/rail.d.ts +2 -5
- package/dist/layouts/containers/rail.d.ts.map +1 -1
- package/dist/layouts/containers/rail.js +17 -55
- package/dist/layouts/containers/rail.js.map +1 -1
- package/dist/layouts/containers/rows/index.d.ts +3 -0
- package/dist/layouts/containers/rows/index.d.ts.map +1 -0
- package/dist/layouts/containers/rows/index.js +7 -0
- package/dist/layouts/containers/rows/index.js.map +1 -0
- package/dist/layouts/containers/rows/row.d.ts +6 -0
- package/dist/layouts/containers/rows/row.d.ts.map +1 -0
- package/dist/layouts/containers/rows/row.js +20 -0
- package/dist/layouts/containers/rows/row.js.map +1 -0
- package/dist/layouts/containers/rows/rows.d.ts +11 -0
- package/dist/layouts/containers/rows/rows.d.ts.map +1 -0
- package/dist/layouts/containers/rows/rows.js +34 -0
- package/dist/layouts/containers/rows/rows.js.map +1 -0
- package/dist/layouts/containers/scaffold.d.ts +2 -5
- package/dist/layouts/containers/scaffold.d.ts.map +1 -1
- package/dist/layouts/containers/scaffold.js +17 -55
- package/dist/layouts/containers/scaffold.js.map +1 -1
- package/dist/layouts/index.d.ts +2 -0
- package/dist/layouts/index.d.ts.map +1 -1
- package/dist/layouts/index.js +26 -22
- package/dist/layouts/index.js.map +1 -1
- package/dist/mobile/inputs/date_picker/mobile_date_picker_header.js +5 -2
- package/dist/mobile/inputs/date_picker/mobile_date_picker_header.js.map +1 -1
- package/dist/mobile/inputs/date_picker/mobile_date_picker_input.js +5 -2
- package/dist/mobile/inputs/date_picker/mobile_date_picker_input.js.map +1 -1
- package/dist/mobile/inputs/date_picker/mobile_date_picker_year_selector.js +8 -5
- package/dist/mobile/inputs/date_picker/mobile_date_picker_year_selector.js.map +1 -1
- package/dist/navigation/tabs/state/link/tab_link.js +9 -6
- package/dist/navigation/tabs/state/link/tab_link.js.map +1 -1
- package/dist/overlay/menu/menu.js +3 -0
- package/dist/overlay/menu/menu.js.map +1 -1
- package/dist/overlay/popper/context_popper.js +8 -5
- package/dist/overlay/popper/context_popper.js.map +1 -1
- package/dist/overlay/popper/element_popper.js +9 -6
- package/dist/overlay/popper/element_popper.js.map +1 -1
- package/dist/overlay/popper/legacy/popper.js +13 -10
- package/dist/overlay/popper/legacy/popper.js.map +1 -1
- package/dist/overlay/popper/preview_popper.js +10 -7
- package/dist/overlay/popper/preview_popper.js.map +1 -1
- package/dist/overlay/tethered/tethered.js +11 -8
- package/dist/overlay/tethered/tethered.js.map +1 -1
- package/dist/resizable.css +1 -0
- package/dist/resizable.module-I6iyBAvM.js +5 -0
- package/dist/resizable.module-I6iyBAvM.js.map +1 -0
- package/dist/resize_handle.css +1 -0
- package/dist/row.css +1 -0
- package/dist/stacks/box/box.js +12 -9
- package/dist/stacks/box/box.js.map +1 -1
- package/dist/stacks/box/detect_resize_bounds.d.ts +1 -0
- package/dist/stacks/box/detect_resize_bounds.d.ts.map +1 -1
- package/dist/stacks/box/detect_resize_bounds.js +22 -20
- package/dist/stacks/box/detect_resize_bounds.js.map +1 -1
- package/dist/stacks/h_collapsible_box.js +17 -14
- package/dist/stacks/h_collapsible_box.js.map +1 -1
- package/dist/stacks/v_collapsible_box.js +19 -16
- package/dist/stacks/v_collapsible_box.js.map +1 -1
- package/dist/surfaces/card/card.d.ts.map +1 -1
- package/dist/surfaces/card/card.js +14 -6
- package/dist/surfaces/card/card.js.map +1 -1
- package/dist/surfaces/pop_confirm/pop_confirm.js +4 -2
- package/dist/surfaces/pop_confirm/pop_confirm.js.map +1 -1
- package/dist/test-setup.d.ts +2 -0
- package/dist/test-setup.d.ts.map +1 -0
- package/dist/test-setup.js +10 -0
- package/dist/test-setup.js.map +1 -0
- package/dist/themes/theme.d.ts.map +1 -1
- package/dist/themes/theme.js +17 -22
- package/dist/themes/theme.js.map +1 -1
- package/dist/themes/themes/ergo/ergo_theme.css +1 -1
- package/dist/themes/themes/ergo/ergo_theme.js +201 -21
- package/dist/themes/themes/ergo/ergo_theme.js.map +1 -1
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +39 -26
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/resize/context.d.ts +4 -0
- package/dist/utils/resize/context.d.ts.map +1 -0
- package/dist/utils/resize/context.js +10 -0
- package/dist/utils/resize/context.js.map +1 -0
- package/dist/utils/resize/handle_config.d.ts +32 -0
- package/dist/utils/resize/handle_config.d.ts.map +1 -0
- package/dist/utils/resize/handle_config.js +85 -0
- package/dist/utils/resize/handle_config.js.map +1 -0
- package/dist/utils/resize/index.d.ts +10 -0
- package/dist/utils/resize/index.d.ts.map +1 -0
- package/dist/utils/resize/index.js +16 -0
- package/dist/utils/resize/index.js.map +1 -0
- package/dist/utils/resize/resizable.d.ts +11 -0
- package/dist/utils/resize/resizable.d.ts.map +1 -0
- package/dist/utils/resize/resizable.js +52 -0
- package/dist/utils/resize/resizable.js.map +1 -0
- package/dist/utils/resize/resize_handle.d.ts +7 -0
- package/dist/utils/resize/resize_handle.d.ts.map +1 -0
- package/dist/utils/resize/resize_handle.js +100 -0
- package/dist/utils/resize/resize_handle.js.map +1 -0
- package/dist/utils/resize/resize_strategy.d.ts +47 -0
- package/dist/utils/resize/resize_strategy.d.ts.map +1 -0
- package/dist/utils/resize/resize_strategy.js +108 -0
- package/dist/utils/resize/resize_strategy.js.map +1 -0
- package/dist/utils/resize/types.d.ts +28 -0
- package/dist/utils/resize/types.d.ts.map +1 -0
- package/dist/utils/resize/types.js +2 -0
- package/dist/utils/resize/types.js.map +1 -0
- package/package.json +3 -3
- package/src/layouts/__stories__/columns.stories.tsx +31 -0
- package/src/layouts/__stories__/composed.stories.tsx +77 -8
- package/src/layouts/__stories__/rows.stories.tsx +77 -0
- package/src/layouts/__stories__/utils.tsx +2 -84
- package/src/layouts/containers/columns/column.module.css +3 -2
- package/src/layouts/containers/columns/columns.tsx +29 -3
- package/src/layouts/containers/containers.module.css +27 -29
- package/src/layouts/containers/rail.tsx +9 -51
- package/src/layouts/containers/rows/index.ts +2 -0
- package/src/layouts/containers/rows/row.module.css +15 -0
- package/src/layouts/containers/rows/row.tsx +22 -0
- package/src/layouts/containers/rows/rows.tsx +42 -0
- package/src/layouts/containers/scaffold.tsx +9 -49
- package/src/layouts/index.ts +2 -0
- package/src/stacks/box/detect_resize_bounds.ts +5 -1
- package/src/surfaces/card/card.module.css +5 -0
- package/src/surfaces/card/card.stories.tsx +66 -8
- package/src/surfaces/card/card.tsx +6 -2
- package/src/surfaces/page/page.stories.tsx +84 -4
- package/src/surfaces/panel/__stories__/panel.stories.tsx +84 -9
- package/src/test-setup.ts +11 -0
- package/src/themes/theme.tsx +6 -16
- package/src/themes/themes/ergo/ergo_theme.css +199 -19
- package/src/utils/index.ts +2 -0
- package/src/utils/resize/__stories__/resizable.stories.tsx +214 -0
- package/src/utils/resize/__stories__/resizable_stories.module.css +47 -0
- package/src/utils/resize/__tests__/handle_config.test.ts +269 -0
- package/src/utils/resize/__tests__/resize_strategy.test.ts +163 -0
- package/src/utils/resize/context.ts +9 -0
- package/src/utils/resize/handle_config.ts +142 -0
- package/src/utils/resize/index.ts +37 -0
- package/src/utils/resize/resizable.module.css +5 -0
- package/src/utils/resize/resizable.tsx +97 -0
- package/src/utils/resize/resize_handle.module.css +146 -0
- package/src/utils/resize/resize_handle.tsx +165 -0
- package/src/utils/resize/resize_strategy.ts +190 -0
- package/src/utils/resize/types.ts +64 -0
- package/dist/containers.module-DlGySre0.js +0 -5
- package/dist/containers.module-DlGySre0.js.map +0 -1
|
@@ -634,20 +634,19 @@
|
|
|
634
634
|
.tcn-scaffold {
|
|
635
635
|
--scaffold-divide-footer: var(--divide-footer, 1);
|
|
636
636
|
--scaffold-divide-header: var(--divide-header, 1);
|
|
637
|
-
|
|
637
|
+
/* Since Scaffold now acts as body too - there is no pad inline default - each outer container should set it */
|
|
638
|
+
/* --pad-inline: var(--padding-large); */
|
|
638
639
|
|
|
639
640
|
/* Border appears on nested scaffold/rail when it follows header or utility-bar */
|
|
640
|
-
:where(.tcn-header)
|
|
641
|
-
|
|
642
|
-
:where(.tcn-utility-bar) + :where(.tcn-scaffold),
|
|
643
|
-
:where(.tcn-utility-bar) + :where(.tcn-rail) {
|
|
644
|
-
border-top: calc(var(--scaffold-divide-header) * 1px) solid
|
|
641
|
+
:where(.tcn-header) {
|
|
642
|
+
border-bottom: calc(var(--scaffold-divide-header) * 1px) solid
|
|
645
643
|
var(--ergo-material-border);
|
|
646
644
|
}
|
|
645
|
+
:where(.tcn-utility-bar) {
|
|
646
|
+
border-bottom: 1px solid var(--ergo-material-border);
|
|
647
|
+
}
|
|
647
648
|
|
|
648
|
-
|
|
649
|
-
:where(.tcn-scaffold) + :where(.tcn-footer),
|
|
650
|
-
:where(.tcn-rail) + :where(.tcn-footer) {
|
|
649
|
+
:where(.tcn-footer) {
|
|
651
650
|
border-top: calc(var(--scaffold-divide-footer) * 1px) solid
|
|
652
651
|
var(--ergo-material-border);
|
|
653
652
|
}
|
|
@@ -661,6 +660,7 @@
|
|
|
661
660
|
.tcn-page {
|
|
662
661
|
--divide-header: 0;
|
|
663
662
|
--divide-footer: 0;
|
|
663
|
+
--pad-inline: var(--padding-large);
|
|
664
664
|
--material: var(--background-color-tertiary);
|
|
665
665
|
background-color: var(--material);
|
|
666
666
|
}
|
|
@@ -668,6 +668,7 @@
|
|
|
668
668
|
/* MODAL: */
|
|
669
669
|
.tcn-modal {
|
|
670
670
|
--divide-header: 0;
|
|
671
|
+
--pad-inline: var(--padding-large);
|
|
671
672
|
box-shadow: 0px 4px 34px 0px #00000096;
|
|
672
673
|
border-radius: var(--ergo-shape-radius-medium);
|
|
673
674
|
background-color: var(--background-color-primary);
|
|
@@ -691,6 +692,7 @@
|
|
|
691
692
|
/* DRAWER: */
|
|
692
693
|
.tcn-drawer {
|
|
693
694
|
--divide-header: 0;
|
|
695
|
+
--pad-inline: var(--padding-large);
|
|
694
696
|
box-shadow: 0px 4px 34px 0px #00000096;
|
|
695
697
|
background-color: var(--background-color-primary);
|
|
696
698
|
overflow: hidden;
|
|
@@ -713,6 +715,7 @@
|
|
|
713
715
|
.tcn-window {
|
|
714
716
|
box-shadow: 0px 4px 34px 0px #00000096;
|
|
715
717
|
--divide-header: 0;
|
|
718
|
+
--pad-inline: var(--padding-large);
|
|
716
719
|
border-radius: var(--ergo-shape-radius-medium);
|
|
717
720
|
background-color: var(--background-color-primary);
|
|
718
721
|
overflow: hidden;
|
|
@@ -737,7 +740,7 @@
|
|
|
737
740
|
--tether-pad-size: 16px;
|
|
738
741
|
--pad-inline: var(--padding-medium);
|
|
739
742
|
|
|
740
|
-
.tcn-pop-confirm-scaffold
|
|
743
|
+
.tcn-pop-confirm-scaffold {
|
|
741
744
|
border-radius: var(--ergo-shape-radius-medium);
|
|
742
745
|
box-shadow: 0px 4px 8px 0px rgba(0, 0, 0, 0.4);
|
|
743
746
|
background-color: var(--background-color-primary);
|
|
@@ -794,6 +797,7 @@
|
|
|
794
797
|
.tcn-panel {
|
|
795
798
|
--divide-header: 1;
|
|
796
799
|
--divide-footer: 1;
|
|
800
|
+
--pad-inline: var(--padding-large);
|
|
797
801
|
--material: var(--background-color-primary);
|
|
798
802
|
background-color: var(--material);
|
|
799
803
|
border-radius: var(--ergo-shape-radius-medium);
|
|
@@ -808,6 +812,7 @@
|
|
|
808
812
|
.tcn-aside {
|
|
809
813
|
--divide-header: 1;
|
|
810
814
|
--divide-footer: 1;
|
|
815
|
+
--pad-inline: var(--padding-large);
|
|
811
816
|
|
|
812
817
|
--material: var(--background-color-secondary);
|
|
813
818
|
background-color: var(--material);
|
|
@@ -855,13 +860,6 @@
|
|
|
855
860
|
:where(.tcn-utility-bar) {
|
|
856
861
|
min-height: var(--ergo-sizing-bar-sm);
|
|
857
862
|
}
|
|
858
|
-
|
|
859
|
-
:where(.tcn-scaffold-stack) > :where(.tcn-scaffold) > :where(.tcn-scaffold-stack),
|
|
860
|
-
:where(.tcn-scaffold-stack) > :where(.tcn-rail) > :where(.tcn-rail-stack),
|
|
861
|
-
:where(.tcn-rail-stack) > :where(.tcn-scaffold) > :where(.tcn-scaffold-stack),
|
|
862
|
-
:where(.tcn-rail-stack) > :where(.tcn-rail) > :where(.tcn-rail-stack) {
|
|
863
|
-
padding-inline: var(--padding-medium);
|
|
864
|
-
}
|
|
865
863
|
}
|
|
866
864
|
|
|
867
865
|
/* Columns: */
|
|
@@ -870,6 +868,7 @@
|
|
|
870
868
|
padding: var(--padding-large);
|
|
871
869
|
|
|
872
870
|
:where(.tcn-column) {
|
|
871
|
+
gap: var(--gap-medium);
|
|
873
872
|
border-right: 1px solid var(--ergo-material-border);
|
|
874
873
|
padding-inline-end: var(--padding-medium);
|
|
875
874
|
}
|
|
@@ -880,16 +879,54 @@
|
|
|
880
879
|
}
|
|
881
880
|
}
|
|
882
881
|
|
|
882
|
+
/* Resize handle offsets */
|
|
883
|
+
:where(.tcn-rail.tcn-columns) {
|
|
884
|
+
--resize-offset: calc(-1 * var(--padding-medium));
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
:where(.tcn-rail):not(.tcn-columns) {
|
|
888
|
+
--resize-offset: 0px;
|
|
889
|
+
}
|
|
890
|
+
|
|
883
891
|
.tcn-page {
|
|
884
892
|
:where(.tcn-columns) {
|
|
885
893
|
padding: var(--padding-medium);
|
|
886
894
|
|
|
887
|
-
:where(.tcn-column)
|
|
895
|
+
:where(.tcn-column) {
|
|
896
|
+
gap: var(--gap-medium);
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
> .tcn-column:not(:last-child) {
|
|
888
900
|
padding-inline-end: var(--padding-medium);
|
|
889
901
|
}
|
|
890
902
|
}
|
|
891
903
|
}
|
|
892
904
|
|
|
905
|
+
/* Rows: */
|
|
906
|
+
.tcn-panel,
|
|
907
|
+
.tcn-card {
|
|
908
|
+
:where(.tcn-rows) {
|
|
909
|
+
:where(.tcn-row):not(:last-child) {
|
|
910
|
+
border-bottom: 1px solid var(--ergo-material-border);
|
|
911
|
+
padding-block-end: var(--padding-medium);
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
:where(.tcn-row):not(:first-child) {
|
|
915
|
+
padding-block-start: var(--padding-medium);
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
.tcn-page {
|
|
921
|
+
:where(.tcn-rows) {
|
|
922
|
+
padding: var(--padding-medium);
|
|
923
|
+
|
|
924
|
+
:where(.tcn-row):not(:last-child) {
|
|
925
|
+
padding-block-end: var(--padding-medium);
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
|
|
893
930
|
/* SECTION */
|
|
894
931
|
.tcn-section {
|
|
895
932
|
--max-section-depth: 4;
|
|
@@ -938,7 +975,7 @@
|
|
|
938
975
|
padding-inline-end: var(--pad-inline, var(--padding-medium));
|
|
939
976
|
}
|
|
940
977
|
|
|
941
|
-
.tcn-scaffold
|
|
978
|
+
.tcn-scaffold > .tcn-detail {
|
|
942
979
|
padding-inline: var(--pad-inline, var(--padding-medium));
|
|
943
980
|
}
|
|
944
981
|
|
|
@@ -1423,4 +1460,147 @@
|
|
|
1423
1460
|
--accent-color: var(--ergo-accent-blue);
|
|
1424
1461
|
}
|
|
1425
1462
|
}
|
|
1463
|
+
|
|
1464
|
+
/* ===== Resize Handle ===== */
|
|
1465
|
+
|
|
1466
|
+
/* Edge indicators: centered pill chip */
|
|
1467
|
+
.tcn-resize-handle[data-axis="horizontal"] {
|
|
1468
|
+
width: 8px;
|
|
1469
|
+
}
|
|
1470
|
+
|
|
1471
|
+
.tcn-resize-handle[data-axis="vertical"] {
|
|
1472
|
+
height: 8px;
|
|
1473
|
+
}
|
|
1474
|
+
|
|
1475
|
+
.tcn-resize-handle[data-axis="horizontal"]::after,
|
|
1476
|
+
.tcn-resize-handle[data-axis="vertical"]::after {
|
|
1477
|
+
content: "";
|
|
1478
|
+
position: absolute;
|
|
1479
|
+
border-radius: var(--ergo-shape-radius-medium);
|
|
1480
|
+
background-color: var(--ergo-grey-light);
|
|
1481
|
+
pointer-events: none;
|
|
1482
|
+
transition: background-color 0.3s;
|
|
1483
|
+
top: 50%;
|
|
1484
|
+
left: 50%;
|
|
1485
|
+
transform: translate(-50%, -50%);
|
|
1486
|
+
}
|
|
1487
|
+
|
|
1488
|
+
.tcn-resize-handle[data-axis="horizontal"]::after {
|
|
1489
|
+
width: 4px;
|
|
1490
|
+
height: 16px;
|
|
1491
|
+
}
|
|
1492
|
+
|
|
1493
|
+
.tcn-resize-handle[data-axis="vertical"]::after {
|
|
1494
|
+
width: 16px;
|
|
1495
|
+
height: 4px;
|
|
1496
|
+
}
|
|
1497
|
+
|
|
1498
|
+
/* Corner L-shape indicator */
|
|
1499
|
+
.tcn-resize-handle[data-axis="corner"]::after {
|
|
1500
|
+
content: "";
|
|
1501
|
+
position: absolute;
|
|
1502
|
+
width: 8px;
|
|
1503
|
+
height: 8px;
|
|
1504
|
+
border-style: solid;
|
|
1505
|
+
border-color: var(--ergo-grey-light);
|
|
1506
|
+
border-width: 0;
|
|
1507
|
+
pointer-events: none;
|
|
1508
|
+
transition: border-color 0.15s;
|
|
1509
|
+
}
|
|
1510
|
+
|
|
1511
|
+
/* Physical corners */
|
|
1512
|
+
.tcn-resize-handle[data-position="top-left"]::after {
|
|
1513
|
+
top: 0;
|
|
1514
|
+
left: 0;
|
|
1515
|
+
border-top-width: 4px;
|
|
1516
|
+
border-left-width: 4px;
|
|
1517
|
+
}
|
|
1518
|
+
|
|
1519
|
+
.tcn-resize-handle[data-position="top-right"]::after {
|
|
1520
|
+
top: 0;
|
|
1521
|
+
right: 0;
|
|
1522
|
+
border-top-width: 4px;
|
|
1523
|
+
border-right-width: 4px;
|
|
1524
|
+
}
|
|
1525
|
+
|
|
1526
|
+
.tcn-resize-handle[data-position="bottom-left"]::after {
|
|
1527
|
+
bottom: 0;
|
|
1528
|
+
left: 0;
|
|
1529
|
+
border-bottom-width: 4px;
|
|
1530
|
+
border-left-width: 4px;
|
|
1531
|
+
}
|
|
1532
|
+
|
|
1533
|
+
.tcn-resize-handle[data-position="bottom-right"]::after {
|
|
1534
|
+
bottom: 0;
|
|
1535
|
+
right: 0;
|
|
1536
|
+
border-bottom-width: 4px;
|
|
1537
|
+
border-right-width: 4px;
|
|
1538
|
+
}
|
|
1539
|
+
|
|
1540
|
+
/* Logical corners (RTL-aware) */
|
|
1541
|
+
.tcn-resize-handle[data-position="top-start"]:dir(ltr)::after {
|
|
1542
|
+
top: 0;
|
|
1543
|
+
left: 0;
|
|
1544
|
+
border-top-width: 4px;
|
|
1545
|
+
border-left-width: 4px;
|
|
1546
|
+
}
|
|
1547
|
+
|
|
1548
|
+
.tcn-resize-handle[data-position="top-start"]:dir(rtl)::after {
|
|
1549
|
+
top: 0;
|
|
1550
|
+
right: 0;
|
|
1551
|
+
border-top-width: 4px;
|
|
1552
|
+
border-right-width: 4px;
|
|
1553
|
+
}
|
|
1554
|
+
|
|
1555
|
+
.tcn-resize-handle[data-position="top-end"]:dir(ltr)::after {
|
|
1556
|
+
top: 0;
|
|
1557
|
+
right: 0;
|
|
1558
|
+
border-top-width: 4px;
|
|
1559
|
+
border-right-width: 4px;
|
|
1560
|
+
}
|
|
1561
|
+
|
|
1562
|
+
.tcn-resize-handle[data-position="top-end"]:dir(rtl)::after {
|
|
1563
|
+
top: 0;
|
|
1564
|
+
left: 0;
|
|
1565
|
+
border-top-width: 4px;
|
|
1566
|
+
border-left-width: 4px;
|
|
1567
|
+
}
|
|
1568
|
+
|
|
1569
|
+
.tcn-resize-handle[data-position="bottom-start"]:dir(ltr)::after {
|
|
1570
|
+
bottom: 0;
|
|
1571
|
+
left: 0;
|
|
1572
|
+
border-bottom-width: 4px;
|
|
1573
|
+
border-left-width: 4px;
|
|
1574
|
+
}
|
|
1575
|
+
|
|
1576
|
+
.tcn-resize-handle[data-position="bottom-start"]:dir(rtl)::after {
|
|
1577
|
+
bottom: 0;
|
|
1578
|
+
right: 0;
|
|
1579
|
+
border-bottom-width: 4px;
|
|
1580
|
+
border-right-width: 4px;
|
|
1581
|
+
}
|
|
1582
|
+
|
|
1583
|
+
.tcn-resize-handle[data-position="bottom-end"]:dir(ltr)::after {
|
|
1584
|
+
bottom: 0;
|
|
1585
|
+
right: 0;
|
|
1586
|
+
border-bottom-width: 4px;
|
|
1587
|
+
border-right-width: 4px;
|
|
1588
|
+
}
|
|
1589
|
+
|
|
1590
|
+
.tcn-resize-handle[data-position="bottom-end"]:dir(rtl)::after {
|
|
1591
|
+
bottom: 0;
|
|
1592
|
+
left: 0;
|
|
1593
|
+
border-bottom-width: 4px;
|
|
1594
|
+
border-left-width: 4px;
|
|
1595
|
+
}
|
|
1596
|
+
|
|
1597
|
+
/* Hover */
|
|
1598
|
+
.tcn-resize-handle[data-axis="horizontal"]:hover::after,
|
|
1599
|
+
.tcn-resize-handle[data-axis="vertical"]:hover::after {
|
|
1600
|
+
background-color: var(--ergo-grey-dark);
|
|
1601
|
+
}
|
|
1602
|
+
|
|
1603
|
+
.tcn-resize-handle:hover::after {
|
|
1604
|
+
border-color: var(--ergo-grey-dark);
|
|
1605
|
+
}
|
|
1426
1606
|
}
|
package/src/utils/index.ts
CHANGED
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import { useRef, useState } from 'react';
|
|
2
|
+
import { Resizable } from '../resizable.js';
|
|
3
|
+
import { ResizeHandle } from '../resize_handle.js';
|
|
4
|
+
import { Box } from '../../../stacks/box/box.js';
|
|
5
|
+
import { VStack } from '../../../stacks/v_stack.js';
|
|
6
|
+
import { BodyText } from '../../../typography/index.js';
|
|
7
|
+
import styles from './resizable_stories.module.css';
|
|
8
|
+
|
|
9
|
+
export default {
|
|
10
|
+
title: 'Utils/Resizable',
|
|
11
|
+
component: Resizable,
|
|
12
|
+
tags: ['autodocs'],
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export const HorizontalResize = () => {
|
|
16
|
+
const [width, setWidth] = useState(300);
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<VStack gap="8px" padding="16px" minHeight="400px">
|
|
20
|
+
<BodyText>Drag the right edge to resize horizontally.</BodyText>
|
|
21
|
+
<Resizable onWidthResize={({ width: w }) => setWidth(Math.round(w))}>
|
|
22
|
+
<Box width={`${width}px`} height="200px" className={styles['demo-box']}>
|
|
23
|
+
<BodyText>Resizable content</BodyText>
|
|
24
|
+
<div className={styles['size-display']}>width: {width}px</div>
|
|
25
|
+
</Box>
|
|
26
|
+
<ResizeHandle position="right" className={styles['demo-handle']} />
|
|
27
|
+
</Resizable>
|
|
28
|
+
</VStack>
|
|
29
|
+
);
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const VerticalResize = () => {
|
|
33
|
+
const [height, setHeight] = useState(200);
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<VStack gap="8px" padding="16px" minHeight="600px">
|
|
37
|
+
<BodyText>Drag the bottom edge to resize vertically.</BodyText>
|
|
38
|
+
<Resizable onHeightResize={({ height: h }) => setHeight(Math.round(h))}>
|
|
39
|
+
<Box width="400px" height={`${height}px`} className={styles['demo-box']}>
|
|
40
|
+
<BodyText>Resizable content</BodyText>
|
|
41
|
+
<div className={styles['size-display']}>height: {height}px</div>
|
|
42
|
+
</Box>
|
|
43
|
+
<ResizeHandle position="bottom" className={styles['demo-handle']} />
|
|
44
|
+
</Resizable>
|
|
45
|
+
</VStack>
|
|
46
|
+
);
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export const CornerResize = () => {
|
|
50
|
+
const [width, setWidth] = useState(300);
|
|
51
|
+
const [height, setHeight] = useState(200);
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<VStack gap="8px" padding="16px" minHeight="600px">
|
|
55
|
+
<BodyText>
|
|
56
|
+
Drag the bottom-right corner to resize both axes simultaneously.
|
|
57
|
+
</BodyText>
|
|
58
|
+
<Resizable
|
|
59
|
+
onWidthResize={({ width: w }) => setWidth(Math.round(w))}
|
|
60
|
+
onHeightResize={({ height: h }) => setHeight(Math.round(h))}
|
|
61
|
+
>
|
|
62
|
+
<Box width={`${width}px`} height={`${height}px`} className={styles['demo-box']}>
|
|
63
|
+
<BodyText>Resizable content</BodyText>
|
|
64
|
+
<div className={styles['size-display']}>
|
|
65
|
+
{width}px × {height}px
|
|
66
|
+
</div>
|
|
67
|
+
</Box>
|
|
68
|
+
<ResizeHandle position="bottom-right" className={styles['demo-handle']} />
|
|
69
|
+
</Resizable>
|
|
70
|
+
</VStack>
|
|
71
|
+
);
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
export const MultipleHandles = () => {
|
|
75
|
+
const [width, setWidth] = useState(400);
|
|
76
|
+
const [height, setHeight] = useState(300);
|
|
77
|
+
|
|
78
|
+
return (
|
|
79
|
+
<VStack gap="8px" padding="16px" minHeight="600px">
|
|
80
|
+
<BodyText>Left, right, bottom edges and bottom-right corner — all active.</BodyText>
|
|
81
|
+
<Resizable
|
|
82
|
+
onWidthResize={({ width: w }) => setWidth(Math.round(w))}
|
|
83
|
+
onHeightResize={({ height: h }) => setHeight(Math.round(h))}
|
|
84
|
+
>
|
|
85
|
+
<Box width={`${width}px`} height={`${height}px`} className={styles['demo-box']}>
|
|
86
|
+
<BodyText>Resizable content</BodyText>
|
|
87
|
+
<div className={styles['size-display']}>
|
|
88
|
+
{width}px × {height}px
|
|
89
|
+
</div>
|
|
90
|
+
</Box>
|
|
91
|
+
<ResizeHandle position="left" className={styles['demo-handle']} />
|
|
92
|
+
<ResizeHandle position="right" className={styles['demo-handle']} />
|
|
93
|
+
<ResizeHandle position="bottom" className={styles['demo-handle']} />
|
|
94
|
+
<ResizeHandle
|
|
95
|
+
position="bottom-right"
|
|
96
|
+
className={styles['demo-handle']}
|
|
97
|
+
style={{
|
|
98
|
+
zIndex: 2,
|
|
99
|
+
}}
|
|
100
|
+
/>
|
|
101
|
+
</Resizable>
|
|
102
|
+
</VStack>
|
|
103
|
+
);
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
export const RTL = () => {
|
|
107
|
+
const [widthStart, setWidthStart] = useState(300);
|
|
108
|
+
const [widthLeft, setWidthLeft] = useState(300);
|
|
109
|
+
|
|
110
|
+
return (
|
|
111
|
+
<VStack gap="16px" padding="16px" minHeight="400px">
|
|
112
|
+
<BodyText>
|
|
113
|
+
RTL context: "start" flips to the right edge, "left" stays
|
|
114
|
+
physical left.
|
|
115
|
+
</BodyText>
|
|
116
|
+
<div className={styles['rtl-container']}>
|
|
117
|
+
<VStack gap="16px">
|
|
118
|
+
<BodyText>position="start" (logical — flips in RTL)</BodyText>
|
|
119
|
+
<Resizable onWidthResize={({ width: w }) => setWidthStart(Math.round(w))}>
|
|
120
|
+
<Box width={`${widthStart}px`} height="100px" className={styles['demo-box']}>
|
|
121
|
+
<div className={styles['size-display']}>start handle: {widthStart}px</div>
|
|
122
|
+
</Box>
|
|
123
|
+
<ResizeHandle position="start" className={styles['demo-handle']} />
|
|
124
|
+
</Resizable>
|
|
125
|
+
|
|
126
|
+
<BodyText>position="left" (physical — stays on left in RTL)</BodyText>
|
|
127
|
+
<Resizable onWidthResize={({ width: w }) => setWidthLeft(Math.round(w))}>
|
|
128
|
+
<Box width={`${widthLeft}px`} height="100px" className={styles['demo-box']}>
|
|
129
|
+
<div className={styles['size-display']}>left handle: {widthLeft}px</div>
|
|
130
|
+
</Box>
|
|
131
|
+
<ResizeHandle position="left" className={styles['demo-handle']} />
|
|
132
|
+
</Resizable>
|
|
133
|
+
</VStack>
|
|
134
|
+
</div>
|
|
135
|
+
</VStack>
|
|
136
|
+
);
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
export const NestedResizable = () => {
|
|
140
|
+
const [outerWidth, setOuterWidth] = useState(500);
|
|
141
|
+
const [innerWidth, setInnerWidth] = useState(250);
|
|
142
|
+
|
|
143
|
+
return (
|
|
144
|
+
<VStack gap="8px" padding="16px" minHeight="400px">
|
|
145
|
+
<BodyText>Nested: each handle binds to its nearest Resizable provider.</BodyText>
|
|
146
|
+
<Resizable onWidthResize={({ width: w }) => setOuterWidth(Math.round(w))}>
|
|
147
|
+
<Box width={`${outerWidth}px`} height="300px" className={styles['nested-outer']}>
|
|
148
|
+
<BodyText>Outer ({outerWidth}px)</BodyText>
|
|
149
|
+
<Resizable onWidthResize={({ width: w }) => setInnerWidth(Math.round(w))}>
|
|
150
|
+
<Box
|
|
151
|
+
width={`${innerWidth}px`}
|
|
152
|
+
height="150px"
|
|
153
|
+
className={styles['nested-inner']}
|
|
154
|
+
>
|
|
155
|
+
<BodyText>Inner ({innerWidth}px)</BodyText>
|
|
156
|
+
</Box>
|
|
157
|
+
<ResizeHandle position="right" className={styles['demo-handle']} />
|
|
158
|
+
</Resizable>
|
|
159
|
+
</Box>
|
|
160
|
+
<ResizeHandle position="right" className={styles['demo-handle']} />
|
|
161
|
+
</Resizable>
|
|
162
|
+
</VStack>
|
|
163
|
+
);
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
export const OverflowHidden = () => {
|
|
167
|
+
const [width, setWidth] = useState(300);
|
|
168
|
+
|
|
169
|
+
return (
|
|
170
|
+
<VStack gap="8px" padding="16px" minHeight="400px">
|
|
171
|
+
<BodyText>
|
|
172
|
+
Outer box is the resize target (minWidth: 100px). Inner box clips content with
|
|
173
|
+
overflow:hidden. Shrink below 200px to clip the purple box. It stops at 100px due
|
|
174
|
+
to the min-width constraint.
|
|
175
|
+
</BodyText>
|
|
176
|
+
<Resizable onWidthResize={({ width: w }) => setWidth(Math.round(w))}>
|
|
177
|
+
<Box width={`${width}px`} minWidth="100px" height="200px">
|
|
178
|
+
<Box height="100%" overflow="hidden" className={styles['demo-box']}>
|
|
179
|
+
<Box minWidth="200px" height="80px" className={styles['clip-target']} />
|
|
180
|
+
<div className={styles['size-display']}>width: {width}px</div>
|
|
181
|
+
</Box>
|
|
182
|
+
</Box>
|
|
183
|
+
<ResizeHandle position="right" className={styles['demo-handle']} />
|
|
184
|
+
</Resizable>
|
|
185
|
+
</VStack>
|
|
186
|
+
);
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
export const CustomHandle = () => {
|
|
190
|
+
const handleRef = useRef<HTMLDivElement>(null);
|
|
191
|
+
const [width, setWidth] = useState(300);
|
|
192
|
+
|
|
193
|
+
return (
|
|
194
|
+
<VStack gap="8px" padding="16px" minHeight="400px">
|
|
195
|
+
<BodyText>Custom styled handle with forwarded ref and aria attributes.</BodyText>
|
|
196
|
+
<Resizable onWidthResize={({ width: w }) => setWidth(Math.round(w))}>
|
|
197
|
+
<Box width={`${width}px`} height="200px" className={styles['demo-box']}>
|
|
198
|
+
<BodyText>Resizable content</BodyText>
|
|
199
|
+
<div className={styles['size-display']}>width: {width}px</div>
|
|
200
|
+
</Box>
|
|
201
|
+
<ResizeHandle
|
|
202
|
+
ref={handleRef}
|
|
203
|
+
position="right"
|
|
204
|
+
style={{
|
|
205
|
+
background: 'rgba(234, 67, 53, 0.4)',
|
|
206
|
+
width: '8px',
|
|
207
|
+
}}
|
|
208
|
+
aria-label="Resize handle"
|
|
209
|
+
data-testid="custom-handle"
|
|
210
|
+
/>
|
|
211
|
+
</Resizable>
|
|
212
|
+
</VStack>
|
|
213
|
+
);
|
|
214
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
@layer tcn-system {
|
|
2
|
+
:where(.demo-box) {
|
|
3
|
+
background: var(--tcn-color-surface-secondary, #f0f0f0);
|
|
4
|
+
border: 1px solid var(--tcn-color-border, #ccc);
|
|
5
|
+
padding: 16px;
|
|
6
|
+
position: relative;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
:where(.demo-handle) {
|
|
10
|
+
background: rgba(0, 120, 212, 0.3);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
:where(.demo-handle:hover) {
|
|
14
|
+
background: rgba(0, 120, 212, 0.6);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
:where(.size-display) {
|
|
18
|
+
font-family: monospace;
|
|
19
|
+
font-size: 12px;
|
|
20
|
+
color: var(--tcn-color-text-secondary, #666);
|
|
21
|
+
margin-top: 8px;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
:where(.rtl-container) {
|
|
25
|
+
direction: rtl;
|
|
26
|
+
border: 2px dashed #999;
|
|
27
|
+
padding: 16px;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
:where(.clip-target) {
|
|
31
|
+
background: #7b1fa2;
|
|
32
|
+
border-radius: 4px;
|
|
33
|
+
flex-shrink: 0;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
:where(.nested-outer) {
|
|
37
|
+
background: #e8f0fe;
|
|
38
|
+
border: 2px solid #4285f4;
|
|
39
|
+
padding: 24px;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
:where(.nested-inner) {
|
|
43
|
+
background: #fce8e6;
|
|
44
|
+
border: 2px solid #ea4335;
|
|
45
|
+
padding: 16px;
|
|
46
|
+
}
|
|
47
|
+
}
|