@vc-shell/framework 1.1.0-alpha.3 → 1.1.0-alpha.4
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/core/composables/index.ts +18 -17
- package/core/composables/useDashboard/index.ts +19 -0
- package/core/composables/{useGlobalSearch.ts → useGlobalSearch/index.ts} +3 -5
- package/core/composables/useWidgets/index.ts +19 -18
- package/core/plugins/modularity/loader.ts +2 -1
- package/core/services/dashboard-service.ts +121 -0
- package/core/services/widget-service.ts +1 -4
- package/dist/core/composables/index.d.ts +1 -0
- package/dist/core/composables/index.d.ts.map +1 -1
- package/dist/core/composables/useDashboard/index.d.ts +5 -0
- package/dist/core/composables/useDashboard/index.d.ts.map +1 -0
- package/dist/core/composables/{useGlobalSearch.d.ts → useGlobalSearch/index.d.ts} +1 -1
- package/dist/core/composables/useGlobalSearch/index.d.ts.map +1 -0
- package/dist/core/plugins/modularity/loader.d.ts.map +1 -1
- package/dist/core/services/dashboard-service.d.ts +33 -0
- package/dist/core/services/dashboard-service.d.ts.map +1 -0
- package/dist/core/services/widget-service.d.ts.map +1 -1
- package/dist/framework.js +235 -225
- package/dist/{index-Bu12RZTu.js → index-8LELHzw9.js} +1 -1
- package/dist/{index-Bwl2ND2Q.js → index-9lJxZE5w.js} +1 -1
- package/dist/{index-CJi-BbTb.js → index-B1YR_MYV.js} +1 -1
- package/dist/{index-BhdwVgUw.js → index-BA98L1jI.js} +1 -1
- package/dist/{index-NdrUF1u3.js → index-BAeTsi-X.js} +1 -1
- package/dist/{index-CbRqPQTw.js → index-BBYyHeYA.js} +1 -1
- package/dist/{index-CsaYfhir.js → index-BrUitdDo.js} +1 -1
- package/dist/{index-CZ_pj3nW.js → index-BuO5ByG9.js} +1 -1
- package/dist/{index-DFPb-jDP.js → index-CJ5I7vTn.js} +1 -1
- package/dist/{index-BdoAu2fz.js → index-CWKrD2Cd.js} +1 -1
- package/dist/{index-DVaMW7gL.js → index-Cf9Tz1ql.js} +1 -1
- package/dist/{index-B89uIUkS.js → index-CrxFDC2b.js} +1 -1
- package/dist/{index-BcQiBkO6.js → index-D1JchciU.js} +1 -1
- package/dist/{index-CEvuTGIu.js → index-DLtsQ_PJ.js} +31254 -31134
- package/dist/{index-COjjAS6v.js → index-DVljTjbf.js} +1 -1
- package/dist/{index-DjQ6Ffv8.js → index-RwX3kiZh.js} +28 -28
- package/dist/{index-S9Ht7s3i.js → index-xLYzNPa7.js} +1 -1
- package/dist/index.css +1 -1
- package/dist/injection-keys.d.ts +28 -0
- package/dist/injection-keys.d.ts.map +1 -1
- package/dist/shared/components/dashboard-widget-card/dashboard-widget-card.vue.d.ts +25 -0
- package/dist/shared/components/dashboard-widget-card/dashboard-widget-card.vue.d.ts.map +1 -0
- package/dist/shared/components/dashboard-widget-card/index.d.ts +2 -0
- package/dist/shared/components/dashboard-widget-card/index.d.ts.map +1 -0
- package/dist/shared/components/draggable-dashboard/DraggableDashboard.vue.d.ts +6 -0
- package/dist/shared/components/draggable-dashboard/DraggableDashboard.vue.d.ts.map +1 -0
- package/dist/shared/components/draggable-dashboard/_internal/DashboardWidget.vue.d.ts +20 -0
- package/dist/shared/components/draggable-dashboard/_internal/DashboardWidget.vue.d.ts.map +1 -0
- package/dist/shared/components/draggable-dashboard/composables/useDashboardDragAndDrop.d.ts +354 -0
- package/dist/shared/components/draggable-dashboard/composables/useDashboardDragAndDrop.d.ts.map +1 -0
- package/dist/shared/components/draggable-dashboard/composables/useDashboardGrid.d.ts +12 -0
- package/dist/shared/components/draggable-dashboard/composables/useDashboardGrid.d.ts.map +1 -0
- package/dist/shared/components/draggable-dashboard/index.d.ts +2 -0
- package/dist/shared/components/draggable-dashboard/index.d.ts.map +1 -0
- package/dist/shared/components/draggable-dashboard/types.d.ts +80 -0
- package/dist/shared/components/draggable-dashboard/types.d.ts.map +1 -0
- package/dist/shared/components/index.d.ts +2 -0
- package/dist/shared/components/index.d.ts.map +1 -1
- package/dist/shared/components/user-dropdown-button/_internal/user-info.vue.d.ts.map +1 -1
- package/dist/shared/components/user-dropdown-button/user-dropdown-button.vue.d.ts.map +1 -1
- package/dist/shared/composables/useMenuExpanded.d.ts +2 -0
- package/dist/shared/composables/useMenuExpanded.d.ts.map +1 -1
- package/dist/shared/modules/dynamic/components/fields/storybook/Button.stories.d.ts +0 -41
- package/dist/shared/modules/dynamic/components/fields/storybook/Button.stories.d.ts.map +1 -1
- package/dist/shared/modules/dynamic/components/fields/storybook/Card.stories.d.ts.map +1 -1
- package/dist/shared/modules/dynamic/components/fields/storybook/common/templates.d.ts +1 -1
- package/dist/shared/modules/dynamic/components/fields/storybook/common/templates.d.ts.map +1 -1
- package/dist/shared/modules/dynamic/pages/dynamic-blade-list.vue.d.ts +2 -25
- package/dist/shared/modules/dynamic/pages/dynamic-blade-list.vue.d.ts.map +1 -1
- package/dist/tailwind.config.d.ts +1 -81
- package/dist/tailwind.config.d.ts.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/ui/components/atoms/vc-button/vc-button.stories.d.ts +169 -734
- package/dist/ui/components/atoms/vc-button/vc-button.stories.d.ts.map +1 -1
- package/dist/ui/components/atoms/vc-button/vc-button.vue.d.ts +18 -2
- package/dist/ui/components/atoms/vc-button/vc-button.vue.d.ts.map +1 -1
- package/dist/ui/components/atoms/vc-card/index.d.ts +2 -0
- package/dist/ui/components/atoms/vc-card/index.d.ts.map +1 -1
- package/dist/ui/components/atoms/vc-card/vc-card.stories.d.ts +12 -0
- package/dist/ui/components/atoms/vc-card/vc-card.stories.d.ts.map +1 -1
- package/dist/ui/components/atoms/vc-card/vc-card.vue.d.ts +2 -0
- package/dist/ui/components/atoms/vc-card/vc-card.vue.d.ts.map +1 -1
- package/dist/ui/components/atoms/vc-icon/icons/GridDotsIcon.vue.d.ts +18 -0
- package/dist/ui/components/atoms/vc-icon/icons/GridDotsIcon.vue.d.ts.map +1 -0
- package/dist/ui/components/atoms/vc-icon/icons/ShoppingCardIcon.vue.d.ts +18 -0
- package/dist/ui/components/atoms/vc-icon/icons/ShoppingCardIcon.vue.d.ts.map +1 -0
- package/dist/ui/components/atoms/vc-icon/icons/index.d.ts +2 -0
- package/dist/ui/components/atoms/vc-icon/icons/index.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-app/_internal/composables/useAppMenuState.d.ts +2 -0
- package/dist/ui/components/organisms/vc-app/_internal/composables/useAppMenuState.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-app/_internal/vc-app-bar/vc-app-bar.vue.d.ts +0 -1
- package/dist/ui/components/organisms/vc-app/_internal/vc-app-bar/vc-app-bar.vue.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-app/_internal/vc-app-menu/_internal/vc-app-menu-item/_internal/vc-app-menu-link.vue.d.ts +2 -1
- package/dist/ui/components/organisms/vc-app/_internal/vc-app-menu/_internal/vc-app-menu-item/_internal/vc-app-menu-link.vue.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-app/_internal/vc-app-menu/vc-app-menu.vue.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-app/vc-app.stories.d.ts +13 -67
- package/dist/ui/components/organisms/vc-app/vc-app.stories.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-app/vc-app.vue.d.ts +5 -65
- package/dist/ui/components/organisms/vc-app/vc-app.vue.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-table/_internal/vc-table-base-header/vc-table-base-header.vue.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-table/_internal/vc-table-desktop-view/_internal/{vc-table-header/vc-table-header.vue.d.ts → vc-table-columns-header/vc-table-columns-header.vue.d.ts} +1 -1
- package/dist/ui/components/organisms/vc-table/_internal/vc-table-desktop-view/_internal/vc-table-columns-header/vc-table-columns-header.vue.d.ts.map +1 -0
- package/dist/ui/components/organisms/vc-table/_internal/vc-table-header/vc-table-header.vue.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-table/_internal/vc-table-mobile-view/vc-table-mobile-view.vue.d.ts +33 -3
- package/dist/ui/components/organisms/vc-table/_internal/vc-table-mobile-view/vc-table-mobile-view.vue.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-table/composables/useTableRowReorder.d.ts.map +1 -1
- package/package.json +10 -5
- package/shared/components/dashboard-widget-card/dashboard-widget-card.vue +67 -0
- package/shared/components/dashboard-widget-card/index.ts +1 -0
- package/shared/components/draggable-dashboard/DraggableDashboard.vue +369 -0
- package/shared/components/draggable-dashboard/_internal/DashboardWidget.vue +133 -0
- package/shared/components/draggable-dashboard/composables/useDashboardDragAndDrop.ts +547 -0
- package/shared/components/draggable-dashboard/composables/useDashboardGrid.ts +250 -0
- package/shared/components/draggable-dashboard/index.ts +1 -0
- package/shared/components/draggable-dashboard/types.ts +91 -0
- package/shared/components/index.ts +2 -0
- package/shared/components/user-dropdown-button/_internal/user-info.vue +25 -12
- package/shared/components/user-dropdown-button/user-dropdown-button.vue +3 -3
- package/shared/composables/useMenuExpanded.ts +24 -0
- package/shared/modules/assets/components/assets-details/assets-details.vue +1 -1
- package/shared/modules/dynamic/components/fields/storybook/Button.stories.ts +186 -247
- package/shared/modules/dynamic/components/fields/storybook/Card.stories.ts +175 -176
- package/shared/modules/dynamic/components/fields/storybook/common/templates.ts +8 -8
- package/shared/modules/dynamic/pages/dynamic-blade-list.vue +153 -187
- package/tailwind.config.ts +127 -126
- package/ui/components/atoms/vc-button/vc-button.stories.ts +1 -16
- package/ui/components/atoms/vc-button/vc-button.vue +74 -63
- package/ui/components/atoms/vc-card/vc-card.stories.ts +102 -102
- package/ui/components/atoms/vc-card/vc-card.vue +164 -159
- package/ui/components/atoms/vc-icon/icons/GridDotsIcon.vue +22 -0
- package/ui/components/atoms/vc-icon/icons/ShoppingCardIcon.vue +16 -0
- package/ui/components/atoms/vc-icon/icons/index.ts +2 -0
- package/ui/components/molecules/vc-field/vc-field.vue +1 -1
- package/ui/components/organisms/vc-app/_internal/composables/useAppMenuState.ts +12 -1
- package/ui/components/organisms/vc-app/_internal/vc-app-bar/_internal/AppBarContent.vue +1 -2
- package/ui/components/organisms/vc-app/_internal/vc-app-bar/_internal/AppBarHeader.vue +1 -1
- package/ui/components/organisms/vc-app/_internal/vc-app-bar/_internal/AppBarOverlay.vue +0 -1
- package/ui/components/organisms/vc-app/_internal/vc-app-bar/vc-app-bar.vue +274 -112
- package/ui/components/organisms/vc-app/_internal/vc-app-menu/_internal/vc-app-menu-item/_internal/vc-app-menu-link.vue +81 -37
- package/ui/components/organisms/vc-app/_internal/vc-app-menu/vc-app-menu.vue +7 -5
- package/ui/components/organisms/vc-app/vc-app.vue +26 -15
- package/ui/components/organisms/vc-table/_internal/vc-table-base-header/vc-table-base-header.vue +5 -7
- package/ui/components/organisms/vc-table/_internal/vc-table-desktop-view/_internal/{vc-table-header/vc-table-header.vue → vc-table-columns-header/vc-table-columns-header.vue} +23 -21
- package/ui/components/organisms/vc-table/_internal/vc-table-desktop-view/_internal/vc-table-row/vc-table-row.vue +1 -0
- package/ui/components/organisms/vc-table/_internal/vc-table-desktop-view/vc-table-desktop-view.vue +1 -1
- package/ui/components/organisms/vc-table/_internal/vc-table-header/vc-table-header.vue +12 -1
- package/ui/components/organisms/vc-table/_internal/vc-table-mobile-view/vc-table-mobile-view.vue +45 -2
- package/ui/components/organisms/vc-table/composables/useTableColumnReorder.ts +5 -5
- package/ui/components/organisms/vc-table/composables/useTableColumnResize.ts +1 -1
- package/ui/components/organisms/vc-table/composables/useTableRowReorder.ts +1 -0
- package/core/services/toolbarbus-service.ts +0 -34
- package/dist/core/composables/useGlobalSearch.d.ts.map +0 -1
- package/dist/core/services/toolbarbus-service.d.ts +0 -10
- package/dist/core/services/toolbarbus-service.d.ts.map +0 -1
- package/dist/ui/components/organisms/vc-app/composables/useToolbarSlots.d.ts +0 -5
- package/dist/ui/components/organisms/vc-app/composables/useToolbarSlots.d.ts.map +0 -1
- package/dist/ui/components/organisms/vc-table/_internal/vc-table-desktop-view/_internal/vc-table-header/vc-table-header.vue.d.ts.map +0 -1
- package/ui/components/organisms/vc-app/composables/useToolbarSlots.ts +0 -37
|
@@ -35,7 +35,17 @@ declare const _default: <T extends string | TableItem>(__VLS_props: {
|
|
|
35
35
|
index: number;
|
|
36
36
|
}) => any>> & Partial<Record<`item_${string}`, (_: {
|
|
37
37
|
item: T;
|
|
38
|
-
cell:
|
|
38
|
+
cell: import("../../../../../../core/types").ITableColumnsBase | (import("../../../../../../core/types").ITableColumnsBase & {
|
|
39
|
+
type: "image";
|
|
40
|
+
emptyIcon?: string | undefined;
|
|
41
|
+
});
|
|
42
|
+
index: number;
|
|
43
|
+
}) => any>> & Partial<Record<`item_${string}`, (_: {
|
|
44
|
+
item: T;
|
|
45
|
+
cell: import("../../../../../../core/types").ITableColumnsBase | (import("../../../../../../core/types").ITableColumnsBase & {
|
|
46
|
+
type: "money";
|
|
47
|
+
currencyField: string;
|
|
48
|
+
});
|
|
39
49
|
index: number;
|
|
40
50
|
}) => any>> & Partial<Record<`item_${string}`, (_: {
|
|
41
51
|
item: T;
|
|
@@ -99,7 +109,17 @@ declare const _default: <T extends string | TableItem>(__VLS_props: {
|
|
|
99
109
|
index: number;
|
|
100
110
|
}) => any>> & Partial<Record<`item_${string}`, (_: {
|
|
101
111
|
item: T;
|
|
102
|
-
cell:
|
|
112
|
+
cell: import("../../../../../../core/types").ITableColumnsBase | (import("../../../../../../core/types").ITableColumnsBase & {
|
|
113
|
+
type: "image";
|
|
114
|
+
emptyIcon?: string | undefined;
|
|
115
|
+
});
|
|
116
|
+
index: number;
|
|
117
|
+
}) => any>> & Partial<Record<`item_${string}`, (_: {
|
|
118
|
+
item: T;
|
|
119
|
+
cell: import("../../../../../../core/types").ITableColumnsBase | (import("../../../../../../core/types").ITableColumnsBase & {
|
|
120
|
+
type: "money";
|
|
121
|
+
currencyField: string;
|
|
122
|
+
});
|
|
103
123
|
index: number;
|
|
104
124
|
}) => any>> & Partial<Record<`item_${string}`, (_: {
|
|
105
125
|
item: T;
|
|
@@ -166,7 +186,17 @@ declare const _default: <T extends string | TableItem>(__VLS_props: {
|
|
|
166
186
|
index: number;
|
|
167
187
|
}) => any>> & Partial<Record<`item_${string}`, (_: {
|
|
168
188
|
item: T;
|
|
169
|
-
cell:
|
|
189
|
+
cell: import("../../../../../../core/types").ITableColumnsBase | (import("../../../../../../core/types").ITableColumnsBase & {
|
|
190
|
+
type: "image";
|
|
191
|
+
emptyIcon?: string | undefined;
|
|
192
|
+
});
|
|
193
|
+
index: number;
|
|
194
|
+
}) => any>> & Partial<Record<`item_${string}`, (_: {
|
|
195
|
+
item: T;
|
|
196
|
+
cell: import("../../../../../../core/types").ITableColumnsBase | (import("../../../../../../core/types").ITableColumnsBase & {
|
|
197
|
+
type: "money";
|
|
198
|
+
currencyField: string;
|
|
199
|
+
});
|
|
170
200
|
index: number;
|
|
171
201
|
}) => any>> & Partial<Record<`item_${string}`, (_: {
|
|
172
202
|
item: T;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vc-table-mobile-view.vue.d.ts","sourceRoot":"","sources":["../../../../../../../ui/components/organisms/vc-table/_internal/vc-table-mobile-view/vc-table-mobile-view.vue.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;;;;;;eA6B5C;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAA;SAAE;eAAS,MAAM;;;aAC9D,MAAM,GAAG,SAAS;eAAS,MAAM;;
|
|
1
|
+
{"version":3,"file":"vc-table-mobile-view.vue.d.ts","sourceRoot":"","sources":["../../../../../../../ui/components/organisms/vc-table/_internal/vc-table-mobile-view/vc-table-mobile-view.vue.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;;;;;;eA6B5C;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAA;SAAE;eAAS,MAAM;;;aAC9D,MAAM,GAAG,SAAS;eAAS,MAAM;;aAsjBvD,aAAa,EAAE;;;;;;;;iBAQX,OAAO;;6BAHK,OAAO;8BACN,IAAI;;WAczB,GAAG;;;;;UAjD4E,GAAG;;;;;;;UACpB,GAAG;;;;;;;UACH,GAAG;;;;UACD,GAAG;;;YAEtC,GAAG;0BACP,GAAG;uBACN,GAAG;;;YAliB1B,WAAW,YAAY,IAAI;YAC3B,gBAAgB,QAAQ;YAAE,OAAO;gBAAE,KAAK,EAAE,MAAM,CAAC;gBAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAA;aAAE,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,GAAG,IAAI;YAClG,YAAY,QAAQ;YAAE,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,GAAG,IAAI;;yCAykB3D,OAAO,KAAK,EAAE,gBAAgB,CAAC,EAAE,CAAC,KAAG,IAAI;;;;;;mBA1kBlB;gBAAE,KAAK,EAAE,MAAM,CAAC;gBAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAA;aAAE;mBAAS,MAAM;;;iBAC9D,MAAM,GAAG,SAAS;mBAAS,MAAM;;iBAsjBvD,aAAa,EAAE;;;;;;;;qBAQX,OAAO;;iCAHK,OAAO;kCACN,IAAI;;oBAahB,OAAO,KAAK,EAAE,gBAAgB,CAAC,EAAE,CAAC,GAAG,IAAI;WAClD,GAAG;;;;;UAjD4E,GAAG;;;;;;;UACpB,GAAG;;;;;;;UACH,GAAG;;;;UACD,GAAG;;;YAEtC,GAAG;0BACP,GAAG;uBACN,GAAG;;;YAliB1B,WAAW,YAAY,IAAI;YAC3B,gBAAgB,QAAQ;YAAE,OAAO;gBAAE,KAAK,EAAE,MAAM,CAAC;gBAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAA;aAAE,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,GAAG,IAAI;YAClG,YAAY,QAAQ;YAAE,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,GAAG,IAAI;;;;;;;;;;;uBADpC;oBAAE,KAAK,EAAE,MAAM,CAAC;oBAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAA;iBAAE;uBAAS,MAAM;;;qBAC9D,MAAM,GAAG,SAAS;uBAAS,MAAM;;qBAsjBvD,aAAa,EAAE;;;;;;;;yBAQX,OAAO;;qCAHK,OAAO;sCACN,IAAI;;wBAahB,OAAO,KAAK,EAAE,gBAAgB,CAAC,EAAE,CAAC,GAAG,IAAI;eAClD,GAAG;;;;;cAjD4E,GAAG;;;;;;;cACpB,GAAG;;;;;;;cACH,GAAG;;;;cACD,GAAG;;;gBAEtC,GAAG;8BACP,GAAG;2BACN,GAAG;;;gBAliB1B,WAAW,YAAY,IAAI;gBAC3B,gBAAgB,QAAQ;gBAAE,OAAO;oBAAE,KAAK,EAAE,MAAM,CAAC;oBAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAA;iBAAE,CAAC;gBAAC,KAAK,EAAE,MAAM,CAAA;aAAE,GAAG,IAAI;gBAClG,YAAY,QAAQ;gBAAE,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;gBAAC,KAAK,EAAE,MAAM,CAAA;aAAE,GAAG,IAAI;;;;AA1B3E,wBAymB2E"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useTableRowReorder.d.ts","sourceRoot":"","sources":["../../../../../../ui/components/organisms/vc-table/composables/useTableRowReorder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,GAAG,EAAE,MAAM,KAAK,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAErC,wBAAgB,kBAAkB,CAAC,CAAC,SAAS,SAAS,GAAG,MAAM,EAC7D,KAAK,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,EACf,SAAS,EAAE,CAAC,IAAI,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,CAAC,EAAE,CAAA;CAAE,KAAK,IAAI;;4BAqBhD,UAAU;4BA6BV,SAAS,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"useTableRowReorder.d.ts","sourceRoot":"","sources":["../../../../../../ui/components/organisms/vc-table/composables/useTableRowReorder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,GAAG,EAAE,MAAM,KAAK,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAErC,wBAAgB,kBAAkB,CAAC,CAAC,SAAS,SAAS,GAAG,MAAM,EAC7D,KAAK,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,EACf,SAAS,EAAE,CAAC,IAAI,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,CAAC,EAAE,CAAA;CAAE,KAAK,IAAI;;4BAqBhD,UAAU;4BA6BV,SAAS,QAAQ,CAAC;2BAqBnB,SAAS,QAAQ,CAAC;4BAqDjB,SAAS;0BAMX,SAAS;uBAaZ,SAAS;EA0BpC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vc-shell/framework",
|
|
3
|
-
"version": "1.1.0-alpha.
|
|
3
|
+
"version": "1.1.0-alpha.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/framework.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -29,7 +29,10 @@
|
|
|
29
29
|
"build:types": "vue-tsc --declaration --emitDeclarationOnly --outDir dist",
|
|
30
30
|
"type-check": "vue-tsc --noEmit",
|
|
31
31
|
"generate-icons": "tsx scripts/generate-icons.mts",
|
|
32
|
-
"check-locales": "tsx scripts/check-locales.mts"
|
|
32
|
+
"check-locales": "tsx scripts/check-locales.mts",
|
|
33
|
+
"test": "vitest run",
|
|
34
|
+
"test:watch": "vitest",
|
|
35
|
+
"test:coverage": "vitest run --coverage"
|
|
33
36
|
},
|
|
34
37
|
"dependencies": {
|
|
35
38
|
"@floating-ui/vue": "^1.0.6",
|
|
@@ -62,10 +65,11 @@
|
|
|
62
65
|
},
|
|
63
66
|
"devDependencies": {
|
|
64
67
|
"@types/dompurify": "^3.0.5",
|
|
65
|
-
"@vc-shell/api-client-generator": "^1.1.0-alpha.
|
|
66
|
-
"@vc-shell/config-generator": "^1.1.0-alpha.
|
|
67
|
-
"@vc-shell/ts-config": "^1.1.0-alpha.
|
|
68
|
+
"@vc-shell/api-client-generator": "^1.1.0-alpha.4",
|
|
69
|
+
"@vc-shell/config-generator": "^1.1.0-alpha.4",
|
|
70
|
+
"@vc-shell/ts-config": "^1.1.0-alpha.4",
|
|
68
71
|
"@vitejs/plugin-vue": "5.0.3",
|
|
72
|
+
"@vue/test-utils": "^2.4.5",
|
|
69
73
|
"cypress-signalr-mock": "^1.5.0",
|
|
70
74
|
"sass": "^1.69.6",
|
|
71
75
|
"shx": "^0.3.4",
|
|
@@ -73,6 +77,7 @@
|
|
|
73
77
|
"tsx": "^4.7.1",
|
|
74
78
|
"typescript": "~5.3.3",
|
|
75
79
|
"vite": "5.3.6",
|
|
80
|
+
"vitest": "^1.3.1",
|
|
76
81
|
"vue-component-type-helpers": "^1.8.27",
|
|
77
82
|
"vue-tsc": "^1.8.27"
|
|
78
83
|
},
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="dashboard-widget-card">
|
|
3
|
+
<div class="dashboard-widget-card__header-wrapper">
|
|
4
|
+
<div class="dashboard-widget-card__header">
|
|
5
|
+
<slot name="header">
|
|
6
|
+
<div class="dashboard-widget-card__header-content">
|
|
7
|
+
<VcIcon
|
|
8
|
+
v-if="icon"
|
|
9
|
+
class="dashboard-widget-card__icon"
|
|
10
|
+
:icon="icon"
|
|
11
|
+
size="xl"
|
|
12
|
+
></VcIcon>
|
|
13
|
+
<div class="dashboard-widget-card__header">{{ props.header }}</div>
|
|
14
|
+
</div>
|
|
15
|
+
</slot>
|
|
16
|
+
</div>
|
|
17
|
+
<div class="dashboard-widget-card__actions">
|
|
18
|
+
<slot name="actions"></slot>
|
|
19
|
+
</div>
|
|
20
|
+
</div>
|
|
21
|
+
<div class="dashboard-widget-card__body">
|
|
22
|
+
<slot></slot>
|
|
23
|
+
</div>
|
|
24
|
+
</div>
|
|
25
|
+
</template>
|
|
26
|
+
|
|
27
|
+
<script setup lang="ts">
|
|
28
|
+
export interface Props {
|
|
29
|
+
header?: string;
|
|
30
|
+
icon?: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const props = defineProps<Props>();
|
|
34
|
+
</script>
|
|
35
|
+
|
|
36
|
+
<style lang="scss">
|
|
37
|
+
:root {
|
|
38
|
+
--dashboard-widget-card-header-color: var(--additional-50);
|
|
39
|
+
--dashboard-widget-card-header-text-color: var(--neutrals-950);
|
|
40
|
+
--dashboard-widget-card-icon-color: var(--neutrals-950);
|
|
41
|
+
--dashboard-widget-card-header-border-color: var(--base-border-color, var(--neutrals-200));
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.dashboard-widget-card {
|
|
45
|
+
@apply tw-rounded-md tw-overflow-hidden tw-h-full tw-bg-[var(--dashboard-widget-card-header-color)];
|
|
46
|
+
|
|
47
|
+
&__header-wrapper {
|
|
48
|
+
@apply tw-p-6 tw-bg-[var(--dashboard-widget-card-header-color)] tw-rounded-t-md tw-border tw-border-[color:var(--dashboard-widget-card-header-border-color)] tw-border-solid tw-flex tw-justify-between tw-items-center tw-text-xl tw-font-bold tw-text-[var(--dashboard-widget-card-header-text-color)];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
&__actions {
|
|
52
|
+
@apply tw-flex tw-items-center tw-gap-[14px];
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
&__header {
|
|
56
|
+
@apply tw-flex;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
&__icon {
|
|
60
|
+
@apply tw-text-[var(--dashboard-widget-card-icon-color)];
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
&__header-content {
|
|
64
|
+
@apply tw-flex tw-items-center tw-gap-[14px];
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
</style>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as DashboardWidgetCard } from "./dashboard-widget-card.vue";
|
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<VcContainer
|
|
3
|
+
no-padding
|
|
4
|
+
class="vc-dashboard-grid"
|
|
5
|
+
>
|
|
6
|
+
<div
|
|
7
|
+
ref="gridContainerRef"
|
|
8
|
+
class="vc-dashboard-grid__container"
|
|
9
|
+
>
|
|
10
|
+
<!-- Position indicator with smooth animation -->
|
|
11
|
+
<div
|
|
12
|
+
v-if="draggedWidget && previewPosition"
|
|
13
|
+
class="vc-dashboard-grid__position-preview"
|
|
14
|
+
:class="{
|
|
15
|
+
'is-animating': isDragging,
|
|
16
|
+
}"
|
|
17
|
+
:style="getPreviewStyles(draggedWidget, previewPosition)"
|
|
18
|
+
></div>
|
|
19
|
+
|
|
20
|
+
<!-- Widgets -->
|
|
21
|
+
<DashboardWidget
|
|
22
|
+
v-for="widget in widgets"
|
|
23
|
+
:key="widget.id"
|
|
24
|
+
:widget="widget"
|
|
25
|
+
:style="getWidgetStyles(widget)"
|
|
26
|
+
:is-dragging="draggedWidget?.id === widget.id"
|
|
27
|
+
:class="{
|
|
28
|
+
'is-dragging': draggedWidget?.id === widget.id,
|
|
29
|
+
'is-displaced': isWidgetDisplaced(widget.id),
|
|
30
|
+
'is-animating': isDragging && (draggedWidget?.id === widget.id || isWidgetDisplaced(widget.id)),
|
|
31
|
+
}"
|
|
32
|
+
:data-id="widget.id"
|
|
33
|
+
@drag="(e: MouseEvent | TouchEvent) => handleMouseDown(e, widget, e.target as HTMLElement)"
|
|
34
|
+
/>
|
|
35
|
+
</div>
|
|
36
|
+
</VcContainer>
|
|
37
|
+
</template>
|
|
38
|
+
|
|
39
|
+
<script setup lang="ts">
|
|
40
|
+
import { ref, onMounted, onUnmounted, defineExpose, computed, watch, onUpdated } from "vue";
|
|
41
|
+
import type { Ref, Component } from "vue";
|
|
42
|
+
import type { IDashboardWidget } from "./types";
|
|
43
|
+
import { useDashboardGrid } from "./composables/useDashboardGrid";
|
|
44
|
+
import { useDashboardDragAndDrop } from "./composables/useDashboardDragAndDrop";
|
|
45
|
+
import { useDashboard } from "../../../core/composables/useDashboard";
|
|
46
|
+
import VcContainer from "../../../ui/components/atoms/vc-container/vc-container.vue";
|
|
47
|
+
import DashboardWidget from "./_internal/DashboardWidget.vue";
|
|
48
|
+
|
|
49
|
+
// Reference to the grid container for coordinate calculations
|
|
50
|
+
const gridContainerRef = ref<HTMLElement | null>(null);
|
|
51
|
+
|
|
52
|
+
// Initialize Grid
|
|
53
|
+
const dashboard = useDashboard();
|
|
54
|
+
const {
|
|
55
|
+
widgets,
|
|
56
|
+
layout,
|
|
57
|
+
|
|
58
|
+
arrangeWidgetsInRows,
|
|
59
|
+
initializeLayout,
|
|
60
|
+
getGridRows,
|
|
61
|
+
} = useDashboardGrid();
|
|
62
|
+
|
|
63
|
+
// Initialize Drag & Drop
|
|
64
|
+
const { draggedWidget, previewPosition, displacedWidgets, isDragging, handleMouseDown, setGridContainer } =
|
|
65
|
+
useDashboardDragAndDrop(dashboard.updateWidgetPosition, getGridRows);
|
|
66
|
+
|
|
67
|
+
// Pass grid container reference to the dragging composable
|
|
68
|
+
watch(gridContainerRef, (container) => {
|
|
69
|
+
if (container) {
|
|
70
|
+
setGridContainer(container);
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// Cached cell size
|
|
75
|
+
const cellSizeCache = ref<{ width: number; height: number } | null>(null);
|
|
76
|
+
// Previous container width
|
|
77
|
+
const previousContainerWidth = ref<number>(0);
|
|
78
|
+
// ResizeObserver instance
|
|
79
|
+
const resizeObserver = ref<ResizeObserver | null>(null);
|
|
80
|
+
// Debounce timer
|
|
81
|
+
const resizeDebounceTimer = ref<number | null>(null);
|
|
82
|
+
|
|
83
|
+
// Function to get cell size with caching
|
|
84
|
+
const getCellSize = () => {
|
|
85
|
+
if (cellSizeCache.value) return cellSizeCache.value;
|
|
86
|
+
if (!gridContainerRef.value) return { width: 0, height: 0 };
|
|
87
|
+
|
|
88
|
+
const rect = gridContainerRef.value.getBoundingClientRect();
|
|
89
|
+
const availableWidth = rect.width - 2 * 18; // Subtract horizontal padding (18px on each side)
|
|
90
|
+
const cellWidthWithGap = availableWidth / 12; // Total width including gap
|
|
91
|
+
|
|
92
|
+
const size = {
|
|
93
|
+
width: Math.max(cellWidthWithGap, 0), // Protection from negative values
|
|
94
|
+
height: 80, // Cell height remains the same
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
cellSizeCache.value = size;
|
|
98
|
+
previousContainerWidth.value = rect.width;
|
|
99
|
+
return size;
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
// Clear cache when window is resized
|
|
103
|
+
const clearCellSizeCache = () => {
|
|
104
|
+
cellSizeCache.value = null;
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
// Recalculate widget positions based on new container size
|
|
108
|
+
const recalculateWidgetPositions = () => {
|
|
109
|
+
// First recalculate cell size to get updated dimensions
|
|
110
|
+
getCellSize();
|
|
111
|
+
|
|
112
|
+
// Update previous width
|
|
113
|
+
if (gridContainerRef.value) {
|
|
114
|
+
previousContainerWidth.value = gridContainerRef.value.getBoundingClientRect().width;
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
// Handle container resize with debounce
|
|
119
|
+
const handleContainerResize = (entries: ResizeObserverEntry[]) => {
|
|
120
|
+
if (!entries.length || isDragging.value) return;
|
|
121
|
+
|
|
122
|
+
const entry = entries[0];
|
|
123
|
+
const newWidth = entry.contentRect.width;
|
|
124
|
+
|
|
125
|
+
// Clear cache to force recalculation of sizes
|
|
126
|
+
clearCellSizeCache();
|
|
127
|
+
|
|
128
|
+
// If width changed significantly (more than 5% or 50px), reposition widgets
|
|
129
|
+
const widthChange = Math.abs(newWidth - previousContainerWidth.value);
|
|
130
|
+
const widthChangePercent = previousContainerWidth.value ? (widthChange / previousContainerWidth.value) * 100 : 0;
|
|
131
|
+
|
|
132
|
+
if (widthChangePercent > 5 || widthChange > 50) {
|
|
133
|
+
recalculateWidgetPositions();
|
|
134
|
+
}
|
|
135
|
+
}; // 300ms debounce
|
|
136
|
+
|
|
137
|
+
// Get styles for preview position indicator
|
|
138
|
+
const getPreviewStyles = (widget: IDashboardWidget, position: { x: number; y: number }) => {
|
|
139
|
+
const cellSize = getCellSize();
|
|
140
|
+
if (!position || !widget?.size) return {};
|
|
141
|
+
|
|
142
|
+
const widgetGap = 20; // Widget gap in pixels
|
|
143
|
+
|
|
144
|
+
return {
|
|
145
|
+
width: `${widget.size.width * cellSize.width - widgetGap}px`,
|
|
146
|
+
height: `${widget.size.height * cellSize.height - widgetGap}px`,
|
|
147
|
+
transform: `translate(${position.x * cellSize.width + widgetGap / 2}px, ${position.y * cellSize.height + widgetGap / 2}px)`,
|
|
148
|
+
};
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
// Helper to check if widget is being displaced
|
|
152
|
+
const isWidgetDisplaced = (widgetId: string) => {
|
|
153
|
+
return displacedWidgets.value.has(widgetId);
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
// Get combined widget styles for absolute positioning
|
|
157
|
+
const getWidgetStyles = computed(() => (widget: IDashboardWidget) => {
|
|
158
|
+
const position = layout.value.get(widget.id);
|
|
159
|
+
if (!position) return { display: "none" };
|
|
160
|
+
|
|
161
|
+
const cellSize = getCellSize();
|
|
162
|
+
const widgetGap = 20; // Widget gap in pixels
|
|
163
|
+
|
|
164
|
+
// Calculate actual dimensions with gaps
|
|
165
|
+
const width = widget.size.width * cellSize.width - widgetGap;
|
|
166
|
+
const height = widget.size.height * cellSize.height - widgetGap;
|
|
167
|
+
|
|
168
|
+
// Calculate position with gaps
|
|
169
|
+
const left = position.x * cellSize.width + widgetGap / 2;
|
|
170
|
+
const top = position.y * cellSize.height + widgetGap / 2;
|
|
171
|
+
|
|
172
|
+
// Base styles for all widgets
|
|
173
|
+
const baseStyles = {
|
|
174
|
+
position: "absolute",
|
|
175
|
+
width: `${width}px`,
|
|
176
|
+
height: `${height}px`,
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
// If widget is being displaced by another widget
|
|
180
|
+
if (isWidgetDisplaced(widget.id)) {
|
|
181
|
+
const newPos = displacedWidgets.value.get(widget.id)!;
|
|
182
|
+
return {
|
|
183
|
+
...baseStyles,
|
|
184
|
+
transform: `translate(${newPos.x * cellSize.width + widgetGap / 2}px, ${newPos.y * cellSize.height + widgetGap / 2}px)`,
|
|
185
|
+
transition: "transform var(--dashboard-transition-duration) var(--dashboard-transition-timing)",
|
|
186
|
+
zIndex: "10",
|
|
187
|
+
} as Record<string, string>;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// If widget is currently being dragged
|
|
191
|
+
if (draggedWidget.value?.id === widget.id) {
|
|
192
|
+
return {
|
|
193
|
+
...baseStyles,
|
|
194
|
+
transform: `translate(${left}px, ${top}px)`,
|
|
195
|
+
opacity: "0", // Hide original since clone is displayed
|
|
196
|
+
pointerEvents: "none",
|
|
197
|
+
zIndex: "1",
|
|
198
|
+
transition: "none", // Disable animations for the source widget
|
|
199
|
+
} as Record<string, string>;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Regular widget
|
|
203
|
+
return {
|
|
204
|
+
...baseStyles,
|
|
205
|
+
transform: `translate(${left}px, ${top}px)`,
|
|
206
|
+
transition: "transform var(--dashboard-transition-duration) var(--dashboard-transition-timing)",
|
|
207
|
+
} as Record<string, string>;
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
// Public method for rearranging widgets
|
|
211
|
+
const rearrangeWidgets = () => {
|
|
212
|
+
arrangeWidgetsInRows(widgets.value);
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
// Public method to manually trigger a layout recalculation
|
|
216
|
+
const recalculateLayout = () => {
|
|
217
|
+
clearCellSizeCache();
|
|
218
|
+
recalculateWidgetPositions();
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
// Add cleanup on component unmount
|
|
222
|
+
onMounted(() => {
|
|
223
|
+
initializeLayout();
|
|
224
|
+
// Initial size calculation
|
|
225
|
+
getCellSize();
|
|
226
|
+
|
|
227
|
+
// Initialize resize observer for the container
|
|
228
|
+
if (gridContainerRef.value && window.ResizeObserver) {
|
|
229
|
+
resizeObserver.value = new ResizeObserver(handleContainerResize);
|
|
230
|
+
resizeObserver.value.observe(gridContainerRef.value);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// Also keep the window resize listener for fallback compatibility
|
|
234
|
+
window.addEventListener("resize", clearCellSizeCache);
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
onUnmounted(() => {
|
|
238
|
+
// Cleanup resize observer
|
|
239
|
+
if (resizeObserver.value) {
|
|
240
|
+
resizeObserver.value.disconnect();
|
|
241
|
+
resizeObserver.value = null;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// Clear debounce timer if any
|
|
245
|
+
if (resizeDebounceTimer.value !== null) {
|
|
246
|
+
window.clearTimeout(resizeDebounceTimer.value);
|
|
247
|
+
resizeDebounceTimer.value = null;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
window.removeEventListener("resize", clearCellSizeCache);
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
// Export public methods
|
|
254
|
+
defineExpose({
|
|
255
|
+
rearrangeWidgets,
|
|
256
|
+
recalculateLayout,
|
|
257
|
+
});
|
|
258
|
+
</script>
|
|
259
|
+
|
|
260
|
+
<style lang="scss">
|
|
261
|
+
:root {
|
|
262
|
+
--dashboard-background: var(--additional-50);
|
|
263
|
+
--dashboard-grid-line: var(--neutrals-200);
|
|
264
|
+
--dashboard-grid-line-active: var(--neutrals-300);
|
|
265
|
+
--dashboard-grid-border: var(--neutrals-300);
|
|
266
|
+
--dashboard-preview-bg: var(--primary-100);
|
|
267
|
+
--dashboard-preview-border: var(--primary-500);
|
|
268
|
+
--dashboard-valid-bg: var(--secondary-100);
|
|
269
|
+
--dashboard-valid-border: var(--secondary-500);
|
|
270
|
+
--dashboard-cell-height: 80px;
|
|
271
|
+
--dashboard-cell-gap-vertical: 24px;
|
|
272
|
+
--dashboard-cell-gap-horizontal: 18px;
|
|
273
|
+
--dashboard-widget-gap: 20px;
|
|
274
|
+
--dashboard-animation-duration: 200ms;
|
|
275
|
+
--dashboard-animation-timing: cubic-bezier(0.4, 0, 0.2, 1);
|
|
276
|
+
--dashboard-transition-duration: 0.35s;
|
|
277
|
+
--dashboard-transition-timing: cubic-bezier(0.25, 0.1, 0.25, 1);
|
|
278
|
+
--dashboard-drag-scale: 1.02;
|
|
279
|
+
--dashboard-gap: 20px;
|
|
280
|
+
--dashboard-widget-shadow-base: 0px 0px 6px -2px rgb(from var(--neutrals-950) r g b / 0.1);
|
|
281
|
+
--dashboard-widget-shadow-elevated: 3px 9px 15px -3px rgb(from var(--neutrals-950) r g b / 0.08);
|
|
282
|
+
--dashboard-position-preview-color: rgb(from var(--primary-500) r g b / 0.15);
|
|
283
|
+
--dashboard-position-preview-border-color: rgb(from var(--primary-500) r g b / 0.5);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
.vc-dashboard-grid {
|
|
287
|
+
@apply tw-w-full tw-h-full;
|
|
288
|
+
background-color: var(--dashboard-background);
|
|
289
|
+
touch-action: none;
|
|
290
|
+
|
|
291
|
+
&__container {
|
|
292
|
+
@apply tw-w-full tw-h-full tw-relative;
|
|
293
|
+
padding: var(--dashboard-cell-gap-vertical) var(--dashboard-cell-gap-horizontal);
|
|
294
|
+
position: relative;
|
|
295
|
+
overflow: auto;
|
|
296
|
+
min-height: calc(var(--dashboard-cell-height) * 12 + var(--dashboard-cell-gap-vertical) * 2);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
&__position-preview {
|
|
300
|
+
position: absolute;
|
|
301
|
+
background-color: var(--dashboard-position-preview-color);
|
|
302
|
+
border: 2px dashed var(--dashboard-position-preview-border-color);
|
|
303
|
+
border-radius: 8px;
|
|
304
|
+
z-index: 100;
|
|
305
|
+
pointer-events: none;
|
|
306
|
+
opacity: 0.8;
|
|
307
|
+
transition: transform var(--dashboard-transition-duration) var(--dashboard-transition-timing);
|
|
308
|
+
|
|
309
|
+
&.is-animating {
|
|
310
|
+
transition: transform var(--dashboard-transition-duration) var(--dashboard-transition-timing);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// Widget styles
|
|
316
|
+
.dashboard-widget {
|
|
317
|
+
position: absolute;
|
|
318
|
+
transition:
|
|
319
|
+
transform var(--dashboard-transition-duration) var(--dashboard-transition-timing),
|
|
320
|
+
opacity 0.2s ease;
|
|
321
|
+
touch-action: none;
|
|
322
|
+
will-change: transform;
|
|
323
|
+
backface-visibility: hidden;
|
|
324
|
+
|
|
325
|
+
&:hover {
|
|
326
|
+
cursor: move;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
&.is-dragging {
|
|
330
|
+
z-index: 1000;
|
|
331
|
+
opacity: 0;
|
|
332
|
+
transition: none !important; /* Turn off all animations when dragging */
|
|
333
|
+
pointer-events: none;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
&.is-displaced {
|
|
337
|
+
z-index: 10;
|
|
338
|
+
transition: transform var(--dashboard-transition-duration) var(--dashboard-transition-timing);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
&.is-animating {
|
|
342
|
+
transition: transform var(--dashboard-transition-duration) var(--dashboard-transition-timing);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
@keyframes collision-pulse {
|
|
347
|
+
0% {
|
|
348
|
+
box-shadow: 0 0 0 0 rgba(var(--danger-500), 0.4);
|
|
349
|
+
}
|
|
350
|
+
70% {
|
|
351
|
+
box-shadow: 0 0 0 10px rgba(var(--danger-500), 0);
|
|
352
|
+
}
|
|
353
|
+
100% {
|
|
354
|
+
box-shadow: 0 0 0 0 rgba(var(--danger-500), 0);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
@keyframes valid-pulse {
|
|
359
|
+
0% {
|
|
360
|
+
opacity: 0.5;
|
|
361
|
+
}
|
|
362
|
+
50% {
|
|
363
|
+
opacity: 0.7;
|
|
364
|
+
}
|
|
365
|
+
100% {
|
|
366
|
+
opacity: 0.5;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
</style>
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
class="dashboard-widget"
|
|
4
|
+
data-test="dashboard-widget"
|
|
5
|
+
@mousedown="handleWidgetMouseDown"
|
|
6
|
+
@touchstart.passive="handleWidgetTouchStart"
|
|
7
|
+
>
|
|
8
|
+
<component
|
|
9
|
+
:is="widget.component"
|
|
10
|
+
v-bind="widget.props || {}"
|
|
11
|
+
class="dashboard-widget__content"
|
|
12
|
+
/>
|
|
13
|
+
</div>
|
|
14
|
+
</template>
|
|
15
|
+
|
|
16
|
+
<script setup lang="ts">
|
|
17
|
+
import type { IDashboardWidget } from "../types";
|
|
18
|
+
|
|
19
|
+
interface Props {
|
|
20
|
+
widget: IDashboardWidget;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
defineProps<Props>();
|
|
24
|
+
|
|
25
|
+
// Список селекторов интерактивных элементов, на которых не должно срабатывать перетаскивание
|
|
26
|
+
const interactiveSelectors = [
|
|
27
|
+
"button",
|
|
28
|
+
"a",
|
|
29
|
+
"input",
|
|
30
|
+
"select",
|
|
31
|
+
"textarea",
|
|
32
|
+
"label",
|
|
33
|
+
'[role="button"]',
|
|
34
|
+
'[role="checkbox"]',
|
|
35
|
+
'[role="radio"]',
|
|
36
|
+
'[role="switch"]',
|
|
37
|
+
'[role="tab"]',
|
|
38
|
+
'[role="link"]',
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
// Проверяем, был ли клик на интерактивном элементе
|
|
42
|
+
const isInteractiveElement = (target: EventTarget | null): boolean => {
|
|
43
|
+
if (!target || !(target instanceof Element)) return false;
|
|
44
|
+
|
|
45
|
+
// Проверяем, соответствует ли элемент или его родители селектору интерактивного элемента
|
|
46
|
+
return interactiveSelectors.some((selector) => {
|
|
47
|
+
return target.matches(selector) || !!target.closest(selector);
|
|
48
|
+
});
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
// Обработчик mousedown
|
|
52
|
+
const handleWidgetMouseDown = (event: MouseEvent) => {
|
|
53
|
+
// Если клик был на интерактивном элементе, не начинаем перетаскивание
|
|
54
|
+
if (isInteractiveElement(event.target)) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Если клик был на пустой области, запускаем перетаскивание
|
|
59
|
+
event.preventDefault();
|
|
60
|
+
event.stopPropagation();
|
|
61
|
+
|
|
62
|
+
// Эмитим событие drag
|
|
63
|
+
emit("drag", event);
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
// Обработчик touchstart
|
|
67
|
+
const handleWidgetTouchStart = (event: TouchEvent) => {
|
|
68
|
+
// Если касание было на интерактивном элементе, не начинаем перетаскивание
|
|
69
|
+
if (isInteractiveElement(event.target)) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Если касание было на пустой области, запускаем перетаскивание
|
|
74
|
+
// Не используем preventDefault здесь, так как уже используем .passive
|
|
75
|
+
emit("drag", event);
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const emit = defineEmits<{
|
|
79
|
+
(e: "drag", event: MouseEvent | TouchEvent): void;
|
|
80
|
+
}>();
|
|
81
|
+
</script>
|
|
82
|
+
|
|
83
|
+
<style lang="scss">
|
|
84
|
+
:root {
|
|
85
|
+
--dashboard-transition-duration: 0.35s;
|
|
86
|
+
--dashboard-transition-timing: cubic-bezier(0.25, 0.1, 0.25, 1);
|
|
87
|
+
--dashboard-widget-shadow-color: rgb(from var(--additional-950) r g b / 0.08);
|
|
88
|
+
--dashboard-widget-shadow-color-secondary: rgb(from var(--additional-950) r g b / 0.06);
|
|
89
|
+
--dashboard-widget-shadow-active: 0px 6px 16px -2px rgb(from var(--additional-950) r g b / 0.12);
|
|
90
|
+
--dashboard-widget-border-radius: 12px;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.dashboard-widget {
|
|
94
|
+
@apply tw-rounded-md;
|
|
95
|
+
border-radius: var(--dashboard-widget-border-radius);
|
|
96
|
+
will-change: transform;
|
|
97
|
+
touch-action: none; /* Prevent default browser touch actions */
|
|
98
|
+
-webkit-tap-highlight-color: transparent; /* Remove tap highlight on mobile */
|
|
99
|
+
user-select: none; /* Prevent text selection on drag */
|
|
100
|
+
-webkit-user-select: none;
|
|
101
|
+
-moz-user-select: none;
|
|
102
|
+
-ms-user-select: none;
|
|
103
|
+
box-shadow:
|
|
104
|
+
0px 1px 4px -1px var(--dashboard-widget-shadow-color),
|
|
105
|
+
0px 4px 10px -2px var(--dashboard-widget-shadow-color-secondary);
|
|
106
|
+
transition:
|
|
107
|
+
transform var(--dashboard-transition-duration) var(--dashboard-transition-timing),
|
|
108
|
+
box-shadow 0.2s ease;
|
|
109
|
+
|
|
110
|
+
&:hover {
|
|
111
|
+
@apply tw-cursor-move;
|
|
112
|
+
transform: translateY(-2px);
|
|
113
|
+
box-shadow: var(--dashboard-widget-shadow-active);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/* Активное состояние для касаний - более выраженный эффект */
|
|
117
|
+
&:active {
|
|
118
|
+
@apply tw-cursor-grabbing;
|
|
119
|
+
transform: scale(1.02);
|
|
120
|
+
box-shadow: var(--dashboard-widget-shadow-active);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
&__content {
|
|
124
|
+
@apply tw-w-full tw-h-full tw-rounded-md;
|
|
125
|
+
border-radius: var(--dashboard-widget-border-radius);
|
|
126
|
+
overflow: hidden; /* Ensure nothing breaks out of the widget */
|
|
127
|
+
position: relative;
|
|
128
|
+
z-index: 1;
|
|
129
|
+
height: 100%;
|
|
130
|
+
pointer-events: all; /* Ensure content receives events */
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
</style>
|