@platforma-sdk/ui-vue 1.66.2 → 1.67.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/.turbo/turbo-build.log +14 -10
- package/.turbo/turbo-formatter$colon$check.log +2 -2
- package/.turbo/turbo-linter$colon$check.log +2 -2
- package/.turbo/turbo-types$colon$check.log +1 -1
- package/CHANGELOG.md +15 -0
- package/dist/__tests__/setup.d.ts +2 -0
- package/dist/__tests__/setup.d.ts.map +1 -0
- package/dist/components/PlAnnotations/components/PlAnnotations.vue2.js.map +1 -1
- package/dist/components/PlDatasetSelector/PlDatasetSelector.js +9 -0
- package/dist/components/PlDatasetSelector/PlDatasetSelector.js.map +1 -0
- package/dist/components/PlDatasetSelector/PlDatasetSelector.style.css +1 -0
- package/dist/components/PlDatasetSelector/PlDatasetSelector.vue.d.ts +105 -0
- package/dist/components/PlDatasetSelector/PlDatasetSelector.vue.d.ts.map +1 -0
- package/dist/components/PlDatasetSelector/PlDatasetSelector.vue2.js +111 -0
- package/dist/components/PlDatasetSelector/PlDatasetSelector.vue2.js.map +1 -0
- package/dist/components/PlDatasetSelector/__tests__/PlDatasetSelector.jsdomtest.d.ts +2 -0
- package/dist/components/PlDatasetSelector/__tests__/PlDatasetSelector.jsdomtest.d.ts.map +1 -0
- package/dist/components/PlDatasetSelector/index.d.ts +2 -0
- package/dist/components/PlDatasetSelector/index.d.ts.map +1 -0
- package/dist/components/PlDatasetSelector/index.js +1 -0
- package/dist/index.js +15 -14
- package/dist/index.js.map +1 -1
- package/dist/lib.d.ts +1 -0
- package/dist/lib.d.ts.map +1 -1
- package/dist/lib.js +2 -0
- package/package.json +9 -7
- package/src/__tests__/setup.ts +10 -0
- package/src/components/PlDatasetSelector/PlDatasetSelector.vue +164 -0
- package/src/components/PlDatasetSelector/__tests__/PlDatasetSelector.jsdomtest.ts +257 -0
- package/src/components/PlDatasetSelector/index.ts +1 -0
- package/src/lib.ts +2 -0
- package/vitest.config.mts +22 -0
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
WARN Issue while reading "/home/runner/_work/platforma/platforma/.npmrc". Failed to replace env in config: ${NPMJS_TOKEN}
|
|
2
2
|
|
|
3
|
-
> @platforma-sdk/ui-vue@1.
|
|
3
|
+
> @platforma-sdk/ui-vue@1.67.0 build /home/runner/_work/platforma/platforma/sdk/ui-vue
|
|
4
4
|
> ts-builder build --target browser-lib
|
|
5
5
|
|
|
6
6
|
Building browser-lib project...
|
|
@@ -12,11 +12,11 @@ Building browser-lib project...
|
|
|
12
12
|
[7m4[0m export function useGridColumns(props: { api: GridApi }) {
|
|
13
13
|
[7m [0m [91m ~~~~~~~~~~~~~~[0m
|
|
14
14
|
|
|
15
|
-
[2K
|
|
15
|
+
[2K
|
|
16
16
|
rendering chunks...
|
|
17
17
|
|
|
18
18
|
[vite:dts] Start generate declaration files...
|
|
19
|
-
[vite:dts] Declaration files built in
|
|
19
|
+
[vite:dts] Declaration files built in 5238ms.
|
|
20
20
|
|
|
21
21
|
computing gzip size...
|
|
22
22
|
dist/components/PlAnnotations/components/PlAnnotations.vue?vue&type=style&index=0&lang.css 0.04 kB │ gzip: 0.06 kB
|
|
@@ -25,6 +25,7 @@ dist/components/BlockLayout.vue?vue&type=style&index=0&lang.css
|
|
|
25
25
|
dist/components/PlAgDataTable/PlAgDataTableSheets.vue?vue&type=style&index=0&lang.css 0.06 kB │ gzip: 0.08 kB
|
|
26
26
|
dist/components/PlAnnotations/components/PlAnnotationsModal.vue?vue&type=style&index=0&lang.css 0.07 kB │ gzip: 0.08 kB
|
|
27
27
|
dist/components/PlAgGridColumnManager/PlAgGridColumnManager.vue?vue&type=style&index=0&lang.css 0.07 kB │ gzip: 0.09 kB
|
|
28
|
+
dist/components/PlDatasetSelector/PlDatasetSelector.vue_vue_type_style_index_0_scoped_b52c3499_lang.css 0.08 kB │ gzip: 0.09 kB
|
|
28
29
|
dist/components/PlAgDataTable/PlAgDataTableV2.vue?vue&type=style&index=0&lang.css 0.09 kB │ gzip: 0.10 kB
|
|
29
30
|
dist/components/PlAnnotations/components/FilterSidebar.vue?vue&type=style&index=0&lang.css 0.11 kB │ gzip: 0.09 kB
|
|
30
31
|
dist/components/PlAgChartHistogramCell/PlAgChartHistogramCell.vue_vue_type_style_index_0_lang.css 0.16 kB │ gzip: 0.13 kB
|
|
@@ -57,6 +58,7 @@ dist/components/PlAgCellProgress/index.js
|
|
|
57
58
|
dist/components/PlAgColumnHeader/index.js 0.03 kB │ gzip: 0.05 kB
|
|
58
59
|
dist/components/PlTableFilters/index.js 0.03 kB │ gzip: 0.05 kB
|
|
59
60
|
dist/components/PlAgCellStatusTag/index.js 0.03 kB │ gzip: 0.05 kB
|
|
61
|
+
dist/components/PlDatasetSelector/index.js 0.03 kB │ gzip: 0.05 kB
|
|
60
62
|
dist/components/PlTableFastSearch/index.js 0.03 kB │ gzip: 0.05 kB
|
|
61
63
|
dist/components/PlAgRowNumCheckbox/index.js 0.03 kB │ gzip: 0.05 kB
|
|
62
64
|
dist/components/PlBtnExportArchive/index.js 0.03 kB │ gzip: 0.05 kB
|
|
@@ -144,6 +146,7 @@ dist/objectHash.js
|
|
|
144
146
|
dist/composition/AgGrid/index.js 0.46 kB │ gzip: 0.32 kB │ map: 0.79 kB
|
|
145
147
|
dist/defineStore.js 0.49 kB │ gzip: 0.32 kB │ map: 1.20 kB
|
|
146
148
|
dist/internal/utils.js 0.50 kB │ gzip: 0.29 kB │ map: 1.08 kB
|
|
149
|
+
dist/components/PlDatasetSelector/PlDatasetSelector.js 0.51 kB │ gzip: 0.29 kB │ map: 1.10 kB
|
|
147
150
|
dist/components/LoaderPage.js 0.52 kB │ gzip: 0.35 kB │ map: 0.48 kB
|
|
148
151
|
dist/components/PlAdvancedFilter/PlAdvancedFilter.vue_vue_type_style_index_0_lang.module.js 0.54 kB │ gzip: 0.29 kB │ map: 0.72 kB
|
|
149
152
|
dist/plugins/Monetization/useButtonTarget.js 0.54 kB │ gzip: 0.35 kB │ map: 1.10 kB
|
|
@@ -198,12 +201,13 @@ dist/plugins/Monetization/UserCabinetCard.vue_vue_type_script_setup_true_lang.js
|
|
|
198
201
|
dist/components/BlockLayout.vue_vue_type_script_setup_true_lang.js 2.18 kB │ gzip: 1.03 kB │ map: 5.92 kB
|
|
199
202
|
dist/components/PlAppErrorNotificationAlert/PlAppErrorNotificationAlert.vue_vue_type_script_setup_true_lang.js 2.40 kB │ gzip: 1.12 kB │ map: 6.67 kB
|
|
200
203
|
dist/components/PlAgDataTable/PlAgDataTableSheets.vue_vue_type_script_setup_true_lang.js 2.45 kB │ gzip: 1.17 kB │ map: 5.01 kB
|
|
201
|
-
dist/lib.js 2.60 kB │ gzip: 0.56 kB │ map: 3.82 kB
|
|
202
204
|
dist/components/PlAnnotations/components/PlAnnotations.vue_vue_type_script_setup_true_lang.js 2.69 kB │ gzip: 1.12 kB │ map: 4.16 kB
|
|
205
|
+
dist/lib.js 2.71 kB │ gzip: 0.57 kB │ map: 3.97 kB
|
|
203
206
|
dist/components/PlAgDataTable/compositions/useGrid.js 2.80 kB │ gzip: 1.24 kB │ map: 6.28 kB
|
|
204
207
|
dist/components/PlAgColumnHeader/PlAgColumnHeader.vue_vue_type_script_setup_true_lang.js 2.93 kB │ gzip: 1.26 kB │ map: 7.97 kB
|
|
205
208
|
dist/components/PlAgDataTable/sources/row-number.js 2.99 kB │ gzip: 1.31 kB │ map: 7.42 kB
|
|
206
209
|
dist/defineApp.js 3.01 kB │ gzip: 1.05 kB │ map: 14.38 kB
|
|
210
|
+
dist/components/PlDatasetSelector/PlDatasetSelector.vue_vue_type_script_setup_true_lang.js 3.09 kB │ gzip: 1.21 kB │ map: 6.90 kB
|
|
207
211
|
dist/components/PlAgGridColumnManager/PlAgGridColumnManager.vue_vue_type_script_setup_true_lang.js 3.14 kB │ gzip: 1.42 kB │ map: 5.04 kB
|
|
208
212
|
dist/plugins/Monetization/LimitCard.vue_vue_type_script_setup_true_lang.js 3.31 kB │ gzip: 1.15 kB │ map: 9.08 kB
|
|
209
213
|
dist/composition/fileContent.js 3.78 kB │ gzip: 1.45 kB │ map: 12.95 kB
|
|
@@ -212,7 +216,7 @@ dist/plugins/Monetization/MonetizationSidebar.vue_vue_type_script_setup_true_lan
|
|
|
212
216
|
dist/components/PlAnnotations/components/FilterSidebar.vue_vue_type_script_setup_true_lang.js 3.97 kB │ gzip: 1.56 kB │ map: 7.42 kB
|
|
213
217
|
dist/internal/createAppV1.js 4.01 kB │ gzip: 1.42 kB │ map: 14.21 kB
|
|
214
218
|
dist/AgGridVue/useAgGridOptions.js 4.23 kB │ gzip: 1.33 kB │ map: 14.12 kB
|
|
215
|
-
dist/index.js 4.
|
|
219
|
+
dist/index.js 4.52 kB │ gzip: 1.37 kB │ map: 0.25 kB
|
|
216
220
|
dist/components/PlTableFilters/PlTableFiltersV2.vue_vue_type_script_setup_true_lang.js 4.63 kB │ gzip: 1.91 kB │ map: 9.02 kB
|
|
217
221
|
dist/components/PlBtnExportArchive/PlBtnExportArchive.vue_vue_type_script_setup_true_lang.js 5.19 kB │ gzip: 2.16 kB │ map: 10.36 kB
|
|
218
222
|
dist/internal/createAppV2.js 5.26 kB │ gzip: 1.98 kB │ map: 17.78 kB
|
|
@@ -224,12 +228,12 @@ dist/components/PlAdvancedFilter/FilterEditor.vue_vue_type_script_setup_true_lan
|
|
|
224
228
|
dist/components/PlAgDataTable/PlAgDataTableV2.vue_vue_type_script_setup_true_lang.js 12.10 kB │ gzip: 3.86 kB │ map: 28.98 kB
|
|
225
229
|
|
|
226
230
|
[33m[33m[PLUGIN_TIMINGS] Warning:[0m Your build spent significant time in plugins. Here is a breakdown:
|
|
227
|
-
- sourcemaps (
|
|
228
|
-
- vite:dts (
|
|
229
|
-
- vite:css-post (
|
|
231
|
+
- sourcemaps (35%)
|
|
232
|
+
- vite:dts (25%)
|
|
233
|
+
- vite:css-post (11%)
|
|
230
234
|
- vite:vue (9%)
|
|
231
|
-
- vite:
|
|
235
|
+
- vite:css (7%)
|
|
232
236
|
See https://rolldown.rs/options/checks#plugintimings for more details.
|
|
233
237
|
[39m
|
|
234
|
-
[32m✓ built in
|
|
238
|
+
[32m✓ built in 6.07s[39m
|
|
235
239
|
Build completed successfully
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
WARN Issue while reading "/home/runner/_work/platforma/platforma/.npmrc". Failed to replace env in config: ${NPMJS_TOKEN}
|
|
2
2
|
|
|
3
|
-
> @platforma-sdk/ui-vue@1.
|
|
3
|
+
> @platforma-sdk/ui-vue@1.67.0 formatter:check /home/runner/_work/platforma/platforma/sdk/ui-vue
|
|
4
4
|
> ts-builder formatter --check
|
|
5
5
|
|
|
6
6
|
Checking formatting...
|
|
@@ -8,5 +8,5 @@ Checking formatting...
|
|
|
8
8
|
Checking formatting...
|
|
9
9
|
|
|
10
10
|
All matched files use the correct format.
|
|
11
|
-
Finished in
|
|
11
|
+
Finished in 3092ms on 136 files using 8 threads.
|
|
12
12
|
Format check completed successfully
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
WARN Issue while reading "/home/runner/_work/platforma/platforma/.npmrc". Failed to replace env in config: ${NPMJS_TOKEN}
|
|
2
2
|
|
|
3
|
-
> @platforma-sdk/ui-vue@1.
|
|
3
|
+
> @platforma-sdk/ui-vue@1.67.0 linter:check /home/runner/_work/platforma/platforma/sdk/ui-vue
|
|
4
4
|
> ts-builder linter --check
|
|
5
5
|
|
|
6
6
|
Linting project...
|
|
7
7
|
↳ oxlint --config /home/runner/_work/platforma/platforma/sdk/ui-vue/.oxlintrc.json --deny-warnings
|
|
8
8
|
Found 0 warnings and 0 errors.
|
|
9
|
-
Finished in
|
|
9
|
+
Finished in 27ms on 119 files with 98 rules using 8 threads.
|
|
10
10
|
Linting completed successfully
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
WARN Issue while reading "/home/runner/_work/platforma/platforma/.npmrc". Failed to replace env in config: ${NPMJS_TOKEN}
|
|
2
2
|
|
|
3
|
-
> @platforma-sdk/ui-vue@1.
|
|
3
|
+
> @platforma-sdk/ui-vue@1.67.0 types:check /home/runner/_work/platforma/platforma/sdk/ui-vue
|
|
4
4
|
> ts-builder type-check --target browser-lib
|
|
5
5
|
|
|
6
6
|
↳ vue-tsc.js --noEmit --project ./tsconfig.json --customConditions ,
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# @platforma-sdk/ui-vue
|
|
2
2
|
|
|
3
|
+
## 1.67.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 10eec21: Add `PlDatasetSelector` component for dataset + optional filter selection. Emits `PrimaryRef`; filter dropdown appears only when the selected dataset has compatible filters (progressive disclosure). Accepts both `PrimaryRef` and plain `PlRef` as input for backward compatibility.
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Updated dependencies [10eec21]
|
|
12
|
+
- Updated dependencies [10eec21]
|
|
13
|
+
- @platforma-sdk/model@1.67.0
|
|
14
|
+
- @milaboratories/pl-model-common@1.35.0
|
|
15
|
+
- @milaboratories/uikit@2.12.9
|
|
16
|
+
- @milaboratories/pf-spec-driver@1.3.3
|
|
17
|
+
|
|
3
18
|
## 1.66.2
|
|
4
19
|
|
|
5
20
|
### Patch Changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/__tests__/setup.ts"],"names":[],"mappings":""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PlAnnotations.vue_vue_type_script_setup_true_lang.js","names":["$style"],"sources":["../../../../src/components/PlAnnotations/components/PlAnnotations.vue"],"sourcesContent":["<script lang=\"ts\">\nimport type { Props as BaseProps } from \"./FilterSidebar.vue\";\nexport type Props = Omit<BaseProps, \"step\" | \"onUpdateStep\"> & {\n annotation: Annotation;\n onUpdateAnnotation: (annotation: Annotation) => void;\n onDeleteSchema?: () => void;\n};\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, effect, shallowRef } from \"vue\";\n\nimport { isNil } from \"@milaboratories/helpers\";\nimport { produce } from \"immer\";\nimport { PlSidebarGroup, useConfirm } from \"@milaboratories/uikit\";\n\nimport type { Annotation, Filter } from \"../types\";\nimport AnnotationsSidebar from \"./AnnotationsSidebar.vue\";\nimport FilterSidebar from \"./FilterSidebar.vue\";\n\nconst props = defineProps<Props>();\n\nconst selectedStepId = shallowRef<undefined | number>(undefined);\n\nconst selectedStep = computed(() => {\n return isNil(selectedStepId.value) || isNil(props.annotation)\n ? undefined\n : props.annotation.steps.find((step) => step.id === selectedStepId.value);\n});\n\neffect(function setDefaultStepId() {\n if (selectedStepId.value === undefined && props.annotation.steps.length > 0) {\n selectedStepId.value = props.annotation.steps[0].id;\n }\n});\n\nconst confirmResetSchema = useConfirm({\n title: \"Reset Schema\",\n message: \"Are you sure you want to reset the schema? This action cannot be undone.\",\n confirmLabel: \"Yes, reset\",\n cancelLabel: \"No, cancel\",\n});\n\nasync function handleDeleteSchema() {\n if (await confirmResetSchema()) {\n selectedStepId.value = undefined;\n props.onDeleteSchema?.();\n }\n}\n\nfunction updateSelectedStepId(id: undefined | number) {\n selectedStepId.value = id;\n}\n\nfunction updateSelectedStep(step: Filter) {\n props.onUpdateAnnotation(\n produce(props.annotation, (draft) => {\n const idx = draft.steps.findIndex((s) => s.id === step.id);\n if (idx !== -1) {\n draft.steps[idx] = step;\n }\n }),\n );\n}\n</script>\n\n<template>\n <PlSidebarGroup>\n <template #item-0>\n <AnnotationsSidebar\n :annotation=\"props.annotation\"\n :selected-step-id=\"selectedStepId\"\n :on-update-annotation=\"props.onUpdateAnnotation\"\n :on-update-selected-step-id=\"updateSelectedStepId\"\n :class=\"$style.sidebarItem\"\n @delete-schema=\"handleDeleteSchema\"\n />\n </template>\n <template #item-1>\n <FilterSidebar\n v-if=\"selectedStep\"\n :step=\"selectedStep\"\n :on-update-step=\"updateSelectedStep\"\n :class=\"$style.sidebarItem\"\n :columns=\"props.columns\"\n :get-suggest-options=\"props.getSuggestOptions\"\n :hasSelectedColumns=\"props.hasSelectedColumns\"\n :getValuesForSelectedColumns=\"props.getValuesForSelectedColumns\"\n />\n </template>\n </PlSidebarGroup>\n</template>\n\n<style module>\n.sidebarItem {\n width: 100%;\n height: 100%;\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;EAoBA,IAAM,IAAQ,GAER,IAAiB,EAA+B,KAAA,EAAU,EAE1D,IAAe,QACZ,EAAM,EAAe,MAAM,IAAI,EAAM,EAAM,WAAU,GACxD,KAAA,IACA,EAAM,WAAW,MAAM,MAAM,MAAS,EAAK,OAAO,EAAe,MAAM,CAC3E;AAEF,IAAO,WAA4B;AACjC,GAAI,EAAe,UAAU,KAAA,KAAa,EAAM,WAAW,MAAM,SAAS,MACxE,EAAe,QAAQ,EAAM,WAAW,MAAM,GAAG;IAEnD;EAEF,IAAM,IAAqB,EAAW;GACpC,OAAO;GACP,SAAS;GACT,cAAc;GACd,aAAa;GACd,CAAC;EAEF,eAAe,IAAqB;AAClC,GAAI,MAAM,GAAoB,KAC5B,EAAe,QAAQ,KAAA,GACvB,EAAM,kBAAkB;;EAI5B,SAAS,EAAqB,GAAwB;AACpD,KAAe,QAAQ;;EAGzB,SAAS,EAAmB,GAAc;AACxC,KAAM,mBACJ,EAAQ,EAAM,aAAa,MAAU;IACnC,IAAM,IAAM,EAAM,MAAM,WAAW,MAAM,EAAE,OAAO,EAAK,GAAG;AAC1D,IAAI,MAAQ,OACV,EAAM,MAAM,KAAO;KAErB,CACH;;yBAKD,EAuBiB,EAAA,EAAA,EAAA,MAAA;GAtBJ,UAAM,QAQb,CAPF,EAOE,GAAA;IANC,YAAY,EAAM;IAClB,oBAAkB,EAAA;IAClB,wBAAsB,EAAM;IAC5B,8BAA4B;IAC5B,OAAK,EAAEA,EAAAA,OAAO,YAAW;IACzB,gBAAe;;;;;;;GAGT,UAAM,
|
|
1
|
+
{"version":3,"file":"PlAnnotations.vue_vue_type_script_setup_true_lang.js","names":["$style"],"sources":["../../../../src/components/PlAnnotations/components/PlAnnotations.vue"],"sourcesContent":["<script lang=\"ts\">\nimport type { Props as BaseProps } from \"./FilterSidebar.vue\";\nexport type Props = Omit<BaseProps, \"step\" | \"onUpdateStep\"> & {\n annotation: Annotation;\n onUpdateAnnotation: (annotation: Annotation) => void;\n onDeleteSchema?: () => void;\n};\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, effect, shallowRef } from \"vue\";\n\nimport { isNil } from \"@milaboratories/helpers\";\nimport { produce } from \"immer\";\nimport { PlSidebarGroup, useConfirm } from \"@milaboratories/uikit\";\n\nimport type { Annotation, Filter } from \"../types\";\nimport AnnotationsSidebar from \"./AnnotationsSidebar.vue\";\nimport FilterSidebar from \"./FilterSidebar.vue\";\n\nconst props = defineProps<Props>();\n\nconst selectedStepId = shallowRef<undefined | number>(undefined);\n\nconst selectedStep = computed(() => {\n return isNil(selectedStepId.value) || isNil(props.annotation)\n ? undefined\n : props.annotation.steps.find((step) => step.id === selectedStepId.value);\n});\n\neffect(function setDefaultStepId() {\n if (selectedStepId.value === undefined && props.annotation.steps.length > 0) {\n selectedStepId.value = props.annotation.steps[0].id;\n }\n});\n\nconst confirmResetSchema = useConfirm({\n title: \"Reset Schema\",\n message: \"Are you sure you want to reset the schema? This action cannot be undone.\",\n confirmLabel: \"Yes, reset\",\n cancelLabel: \"No, cancel\",\n});\n\nasync function handleDeleteSchema() {\n if (await confirmResetSchema()) {\n selectedStepId.value = undefined;\n props.onDeleteSchema?.();\n }\n}\n\nfunction updateSelectedStepId(id: undefined | number) {\n selectedStepId.value = id;\n}\n\nfunction updateSelectedStep(step: Filter) {\n props.onUpdateAnnotation(\n produce(props.annotation, (draft) => {\n const idx = draft.steps.findIndex((s) => s.id === step.id);\n if (idx !== -1) {\n draft.steps[idx] = step;\n }\n }),\n );\n}\n</script>\n\n<template>\n <PlSidebarGroup>\n <template #item-0>\n <AnnotationsSidebar\n :annotation=\"props.annotation\"\n :selected-step-id=\"selectedStepId\"\n :on-update-annotation=\"props.onUpdateAnnotation\"\n :on-update-selected-step-id=\"updateSelectedStepId\"\n :class=\"$style.sidebarItem\"\n @delete-schema=\"handleDeleteSchema\"\n />\n </template>\n <template #item-1>\n <FilterSidebar\n v-if=\"selectedStep\"\n :step=\"selectedStep\"\n :on-update-step=\"updateSelectedStep\"\n :class=\"$style.sidebarItem\"\n :columns=\"props.columns\"\n :get-suggest-options=\"props.getSuggestOptions\"\n :hasSelectedColumns=\"props.hasSelectedColumns\"\n :getValuesForSelectedColumns=\"props.getValuesForSelectedColumns\"\n />\n </template>\n </PlSidebarGroup>\n</template>\n\n<style module>\n.sidebarItem {\n width: 100%;\n height: 100%;\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;EAoBA,IAAM,IAAQ,GAER,IAAiB,EAA+B,KAAA,EAAU,EAE1D,IAAe,QACZ,EAAM,EAAe,MAAM,IAAI,EAAM,EAAM,WAAU,GACxD,KAAA,IACA,EAAM,WAAW,MAAM,MAAM,MAAS,EAAK,OAAO,EAAe,MAAM,CAC3E;AAEF,IAAO,WAA4B;AACjC,GAAI,EAAe,UAAU,KAAA,KAAa,EAAM,WAAW,MAAM,SAAS,MACxE,EAAe,QAAQ,EAAM,WAAW,MAAM,GAAG;IAEnD;EAEF,IAAM,IAAqB,EAAW;GACpC,OAAO;GACP,SAAS;GACT,cAAc;GACd,aAAa;GACd,CAAC;EAEF,eAAe,IAAqB;AAClC,GAAI,MAAM,GAAoB,KAC5B,EAAe,QAAQ,KAAA,GACvB,EAAM,kBAAkB;;EAI5B,SAAS,EAAqB,GAAwB;AACpD,KAAe,QAAQ;;EAGzB,SAAS,EAAmB,GAAc;AACxC,KAAM,mBACJ,EAAQ,EAAM,aAAa,MAAU;IACnC,IAAM,IAAM,EAAM,MAAM,WAAW,MAAM,EAAE,OAAO,EAAK,GAAG;AAC1D,IAAI,MAAQ,OACV,EAAM,MAAM,KAAO;KAErB,CACH;;yBAKD,EAuBiB,EAAA,EAAA,EAAA,MAAA;GAtBJ,UAAM,QAQb,CAPF,EAOE,GAAA;IANC,YAAY,EAAM;IAClB,oBAAkB,EAAA;IAClB,wBAAsB,EAAM;IAC5B,8BAA4B;IAC5B,OAAK,EAAEA,EAAAA,OAAO,YAAW;IACzB,gBAAe;;;;;;;GAGT,UAAM,QAiBZ,CAfK,EAAA,SAAA,GAAA,EADR,EASE,GAAA;;IAPC,MAAM,EAAA;IACN,kBAAgB;IAChB,OAAK,EAAEA,EAAAA,OAAO,YAAW;IACzB,SAAS,EAAM;IACf,uBAAqB,EAAM;IAC3B,oBAAoB,EAAM;IAC1B,6BAA6B,EAAM"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import e from "../../_virtual/_plugin-vue_export-helper.js";
|
|
2
|
+
import t from "./PlDatasetSelector.vue2.js";
|
|
3
|
+
import './PlDatasetSelector.style.css';/* empty css */
|
|
4
|
+
//#region src/components/PlDatasetSelector/PlDatasetSelector.vue
|
|
5
|
+
var n = /* @__PURE__ */ e(t, [["__scopeId", "data-v-b52c3499"]]);
|
|
6
|
+
//#endregion
|
|
7
|
+
export { n as default };
|
|
8
|
+
|
|
9
|
+
//# sourceMappingURL=PlDatasetSelector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PlDatasetSelector.js","names":[],"sources":["../../../src/components/PlDatasetSelector/PlDatasetSelector.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Select a dataset and (optionally) a filter column, emitting a `PrimaryRef`.\n *\n * Behaves like {@link PlDropdownRef} when none of the offered datasets carry\n * filter options. When the selected dataset has compatible filters, a second\n * dropdown appears with the filters plus a \"No filter\" entry.\n *\n * Accepts `PrimaryRef | PlRef | undefined` as `modelValue` (a plain `PlRef`\n * is treated as an unfiltered dataset), but always emits `PrimaryRef`\n * (or `undefined` when cleared).\n */\nexport default {\n name: \"PlDatasetSelector\",\n};\n</script>\n\n<script lang=\"ts\" setup>\nimport type { DatasetOption, PlRef, PrimaryRef } from \"@platforma-sdk/model\";\nimport { createPrimaryRef, isPrimaryRef, plRefsEqual } from \"@platforma-sdk/model\";\nimport type { ListOption } from \"@milaboratories/uikit\";\nimport { PlDropdown, PlDropdownRef } from \"@milaboratories/uikit\";\nimport { computed } from \"vue\";\n\nconst slots = defineSlots<{\n tooltip?: () => unknown;\n}>();\n\n/**\n * v-model value. Accepts `PrimaryRef`, plain `PlRef` (treated as unfiltered),\n * or `undefined`. Writes always emit `PrimaryRef` or `undefined`.\n */\nconst model = defineModel<PrimaryRef | PlRef | undefined>();\n\nconst props = withDefaults(\n defineProps<{\n /** Available datasets, each optionally carrying compatible filter choices. */\n options?: Readonly<DatasetOption[]>;\n /** Label above the dataset dropdown. */\n label?: string;\n /** Helper text below the dataset dropdown (shown when there is no error). */\n helper?: string;\n /** Helper text shown while `options` is undefined (loading). */\n loadingOptionsHelper?: string;\n /** Error message displayed below the dataset dropdown. */\n error?: unknown;\n /** Placeholder when no dataset is selected. */\n placeholder?: string;\n /** Label above the filter dropdown. */\n filterLabel?: string;\n /** Placeholder for the filter dropdown. */\n filterPlaceholder?: string;\n /** Label of the \"no filter\" entry prepended to the filter options. */\n noFilterLabel?: string;\n /** Show a clear button on the dataset dropdown. */\n clearable?: boolean;\n /** Mark the dataset dropdown as required. */\n required?: boolean;\n /** Disable all interaction. */\n disabled?: boolean;\n }>(),\n {\n options: undefined,\n label: undefined,\n helper: undefined,\n loadingOptionsHelper: undefined,\n error: undefined,\n placeholder: \"...\",\n filterLabel: \"\",\n filterPlaceholder: \"...\",\n noFilterLabel: \"No filter\",\n clearable: false,\n required: false,\n disabled: false,\n },\n);\n\nconst selectedDataset = computed<PlRef | undefined>(() => {\n const v = model.value;\n if (v === undefined) return undefined;\n return isPrimaryRef(v) ? v.column : v;\n});\n\nconst selectedFilter = computed<PlRef | undefined>(() => {\n const v = model.value;\n return isPrimaryRef(v) ? v.filter : undefined;\n});\n\nconst currentDatasetOption = computed<DatasetOption | undefined>(() => {\n const dataset = selectedDataset.value;\n if (!dataset) return undefined;\n return props.options?.find((o) => plRefsEqual(o.ref, dataset, true));\n});\n\nconst hasFilters = computed(() => (currentDatasetOption.value?.filters?.length ?? 0) > 0);\n\n/**\n * Filter dropdown options. The first entry (`null`) is the \"No filter\" choice —\n * null distinguishes it from `undefined` (dropdown clear button, disabled here).\n */\nconst filterOptions = computed<ListOption<PlRef | null>[]>(() => {\n const filters = currentDatasetOption.value?.filters;\n if (!filters) return [];\n return [\n { label: props.noFilterLabel, value: null } as ListOption<PlRef | null>,\n ...filters.map((f) => ({ label: f.label, value: f.ref }) as ListOption<PlRef | null>),\n ];\n});\n\nconst filterValue = computed<PlRef | null>(() => selectedFilter.value ?? null);\n\nfunction emitValue(dataset: PlRef | undefined, filter: PlRef | undefined) {\n model.value = dataset === undefined ? undefined : createPrimaryRef(dataset, filter);\n}\n\nfunction onDatasetChange(dataset: PlRef | undefined) {\n emitValue(dataset, undefined);\n}\n\nfunction onFilterChange(value: PlRef | null | undefined) {\n const dataset = selectedDataset.value;\n if (!dataset) return;\n emitValue(dataset, value ?? undefined);\n}\n</script>\n\n<template>\n <div class=\"pl-dataset-selector\">\n <PlDropdownRef\n :model-value=\"selectedDataset\"\n :options=\"options\"\n :label=\"label\"\n :helper=\"helper\"\n :loading-options-helper=\"loadingOptionsHelper\"\n :error=\"error\"\n :placeholder=\"placeholder\"\n :clearable=\"clearable\"\n :required=\"required\"\n :disabled=\"disabled\"\n @update:model-value=\"onDatasetChange\"\n >\n <template v-if=\"slots.tooltip\" #tooltip>\n <slot name=\"tooltip\" />\n </template>\n </PlDropdownRef>\n <PlDropdown\n v-if=\"hasFilters\"\n :model-value=\"filterValue\"\n :options=\"filterOptions\"\n :label=\"filterLabel\"\n :placeholder=\"filterPlaceholder\"\n :disabled=\"disabled\"\n @update:model-value=\"onFilterChange\"\n />\n </div>\n</template>\n\n<style scoped>\n.pl-dataset-selector {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n</style>\n"],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.pl-dataset-selector[data-v-b52c3499]{flex-direction:column;gap:12px;display:flex}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { DatasetOption, PlRef, PrimaryRef } from '@platforma-sdk/model';
|
|
2
|
+
/**
|
|
3
|
+
* Select a dataset and (optionally) a filter column, emitting a `PrimaryRef`.
|
|
4
|
+
*
|
|
5
|
+
* Behaves like {@link PlDropdownRef} when none of the offered datasets carry
|
|
6
|
+
* filter options. When the selected dataset has compatible filters, a second
|
|
7
|
+
* dropdown appears with the filters plus a "No filter" entry.
|
|
8
|
+
*
|
|
9
|
+
* Accepts `PrimaryRef | PlRef | undefined` as `modelValue` (a plain `PlRef`
|
|
10
|
+
* is treated as an unfiltered dataset), but always emits `PrimaryRef`
|
|
11
|
+
* (or `undefined` when cleared).
|
|
12
|
+
*/
|
|
13
|
+
declare const _default: __VLS_WithTemplateSlots<import('vue').DefineComponent<{
|
|
14
|
+
modelValue?: PrimaryRef | PlRef | undefined;
|
|
15
|
+
} & {
|
|
16
|
+
/** Available datasets, each optionally carrying compatible filter choices. */
|
|
17
|
+
options?: Readonly<DatasetOption[]>;
|
|
18
|
+
/** Label above the dataset dropdown. */
|
|
19
|
+
label?: string;
|
|
20
|
+
/** Helper text below the dataset dropdown (shown when there is no error). */
|
|
21
|
+
helper?: string;
|
|
22
|
+
/** Helper text shown while `options` is undefined (loading). */
|
|
23
|
+
loadingOptionsHelper?: string;
|
|
24
|
+
/** Error message displayed below the dataset dropdown. */
|
|
25
|
+
error?: unknown;
|
|
26
|
+
/** Placeholder when no dataset is selected. */
|
|
27
|
+
placeholder?: string;
|
|
28
|
+
/** Label above the filter dropdown. */
|
|
29
|
+
filterLabel?: string;
|
|
30
|
+
/** Placeholder for the filter dropdown. */
|
|
31
|
+
filterPlaceholder?: string;
|
|
32
|
+
/** Label of the "no filter" entry prepended to the filter options. */
|
|
33
|
+
noFilterLabel?: string;
|
|
34
|
+
/** Show a clear button on the dataset dropdown. */
|
|
35
|
+
clearable?: boolean;
|
|
36
|
+
/** Mark the dataset dropdown as required. */
|
|
37
|
+
required?: boolean;
|
|
38
|
+
/** Disable all interaction. */
|
|
39
|
+
disabled?: boolean;
|
|
40
|
+
}, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
|
|
41
|
+
"update:modelValue": (value: PrimaryRef | Readonly<{
|
|
42
|
+
__isRef: true;
|
|
43
|
+
blockId: string;
|
|
44
|
+
name: string;
|
|
45
|
+
requireEnrichments?: true | undefined;
|
|
46
|
+
}> | undefined) => any;
|
|
47
|
+
}, string, import('vue').PublicProps, Readonly<{
|
|
48
|
+
modelValue?: PrimaryRef | PlRef | undefined;
|
|
49
|
+
} & {
|
|
50
|
+
/** Available datasets, each optionally carrying compatible filter choices. */
|
|
51
|
+
options?: Readonly<DatasetOption[]>;
|
|
52
|
+
/** Label above the dataset dropdown. */
|
|
53
|
+
label?: string;
|
|
54
|
+
/** Helper text below the dataset dropdown (shown when there is no error). */
|
|
55
|
+
helper?: string;
|
|
56
|
+
/** Helper text shown while `options` is undefined (loading). */
|
|
57
|
+
loadingOptionsHelper?: string;
|
|
58
|
+
/** Error message displayed below the dataset dropdown. */
|
|
59
|
+
error?: unknown;
|
|
60
|
+
/** Placeholder when no dataset is selected. */
|
|
61
|
+
placeholder?: string;
|
|
62
|
+
/** Label above the filter dropdown. */
|
|
63
|
+
filterLabel?: string;
|
|
64
|
+
/** Placeholder for the filter dropdown. */
|
|
65
|
+
filterPlaceholder?: string;
|
|
66
|
+
/** Label of the "no filter" entry prepended to the filter options. */
|
|
67
|
+
noFilterLabel?: string;
|
|
68
|
+
/** Show a clear button on the dataset dropdown. */
|
|
69
|
+
clearable?: boolean;
|
|
70
|
+
/** Mark the dataset dropdown as required. */
|
|
71
|
+
required?: boolean;
|
|
72
|
+
/** Disable all interaction. */
|
|
73
|
+
disabled?: boolean;
|
|
74
|
+
}> & Readonly<{
|
|
75
|
+
"onUpdate:modelValue"?: ((value: PrimaryRef | Readonly<{
|
|
76
|
+
__isRef: true;
|
|
77
|
+
blockId: string;
|
|
78
|
+
name: string;
|
|
79
|
+
requireEnrichments?: true | undefined;
|
|
80
|
+
}> | undefined) => any) | undefined;
|
|
81
|
+
}>, {
|
|
82
|
+
error: undefined;
|
|
83
|
+
label: string;
|
|
84
|
+
placeholder: string;
|
|
85
|
+
options: Readonly<DatasetOption[]>;
|
|
86
|
+
helper: string;
|
|
87
|
+
loadingOptionsHelper: string;
|
|
88
|
+
clearable: boolean;
|
|
89
|
+
required: boolean;
|
|
90
|
+
disabled: boolean;
|
|
91
|
+
filterLabel: string;
|
|
92
|
+
filterPlaceholder: string;
|
|
93
|
+
noFilterLabel: string;
|
|
94
|
+
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLDivElement>, Readonly<{
|
|
95
|
+
tooltip?: () => unknown;
|
|
96
|
+
}> & {
|
|
97
|
+
tooltip?: () => unknown;
|
|
98
|
+
}>;
|
|
99
|
+
export default _default;
|
|
100
|
+
type __VLS_WithTemplateSlots<T, S> = T & {
|
|
101
|
+
new (): {
|
|
102
|
+
$slots: S;
|
|
103
|
+
};
|
|
104
|
+
};
|
|
105
|
+
//# sourceMappingURL=PlDatasetSelector.vue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PlDatasetSelector.vue.d.ts","sourceRoot":"","sources":["../../../src/components/PlDatasetSelector/PlDatasetSelector.vue"],"names":[],"mappings":"AAsKA,OAAO,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAO7E;;;;;;;;;;GAUG;;iBA0HU,UAAU,GAAG,KAAK,GAAG,SAAS;;IA7GvC,8EAA8E;cACpE,QAAQ,CAAC,aAAa,EAAE,CAAC;IACnC,wCAAwC;YAChC,MAAM;IACd,6EAA6E;aACpE,MAAM;IACf,gEAAgE;2BACzC,MAAM;IAC7B,0DAA0D;YAClD,OAAO;IACf,+CAA+C;kBACjC,MAAM;IACpB,uCAAuC;kBACzB,MAAM;IACpB,2CAA2C;wBACvB,MAAM;IAC1B,sEAAsE;oBACtD,MAAM;IACtB,mDAAmD;gBACvC,OAAO;IACnB,6CAA6C;eAClC,OAAO;IAClB,+BAA+B;eACpB,OAAO;;;;;;;;;iBAsFT,UAAU,GAAG,KAAK,GAAG,SAAS;;IA7GvC,8EAA8E;cACpE,QAAQ,CAAC,aAAa,EAAE,CAAC;IACnC,wCAAwC;YAChC,MAAM;IACd,6EAA6E;aACpE,MAAM;IACf,gEAAgE;2BACzC,MAAM;IAC7B,0DAA0D;YAClD,OAAO;IACf,+CAA+C;kBACjC,MAAM;IACpB,uCAAuC;kBACzB,MAAM;IACpB,2CAA2C;wBACvB,MAAM;IAC1B,sEAAsE;oBACtD,MAAM;IACtB,mDAAmD;gBACvC,OAAO;IACnB,6CAA6C;eAClC,OAAO;IAClB,+BAA+B;eACpB,OAAO;;;;;;;;;;WApBV,MAAM;iBAQA,MAAM;aAVV,QAAQ,CAAC,aAAa,EAAE,CAAC;YAI1B,MAAM;0BAEQ,MAAM;eAYjB,OAAO;cAER,OAAO;cAEP,OAAO;iBAVJ,MAAM;uBAEA,MAAM;mBAEV,MAAM;;cA3Bd,MAAM,OAAO;;cAAb,MAAM,OAAO;;AAFzB,wBAmQK;AAcL,KAAK,uBAAuB,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IACxC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KAEV,CAAA;CACD,CAAC"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { computed as e, createBlock as t, createCommentVNode as n, createElementBlock as r, createSlots as i, createVNode as a, defineComponent as o, mergeModels as s, openBlock as c, renderSlot as l, unref as u, useModel as d, useSlots as f, withCtx as p } from "vue";
|
|
2
|
+
import { createPrimaryRef as m, isPrimaryRef as h, plRefsEqual as g } from "@platforma-sdk/model";
|
|
3
|
+
import { PlDropdown as _, PlDropdownRef as v } from "@milaboratories/uikit";
|
|
4
|
+
//#region src/components/PlDatasetSelector/PlDatasetSelector.vue?vue&type=script&setup=true&lang.ts
|
|
5
|
+
var y = { class: "pl-dataset-selector" }, b = /* @__PURE__ */ o({
|
|
6
|
+
name: "PlDatasetSelector",
|
|
7
|
+
props: /* @__PURE__ */ s({
|
|
8
|
+
options: { default: void 0 },
|
|
9
|
+
label: { default: void 0 },
|
|
10
|
+
helper: { default: void 0 },
|
|
11
|
+
loadingOptionsHelper: { default: void 0 },
|
|
12
|
+
error: { default: void 0 },
|
|
13
|
+
placeholder: { default: "..." },
|
|
14
|
+
filterLabel: { default: "" },
|
|
15
|
+
filterPlaceholder: { default: "..." },
|
|
16
|
+
noFilterLabel: { default: "No filter" },
|
|
17
|
+
clearable: {
|
|
18
|
+
type: Boolean,
|
|
19
|
+
default: !1
|
|
20
|
+
},
|
|
21
|
+
required: {
|
|
22
|
+
type: Boolean,
|
|
23
|
+
default: !1
|
|
24
|
+
},
|
|
25
|
+
disabled: {
|
|
26
|
+
type: Boolean,
|
|
27
|
+
default: !1
|
|
28
|
+
}
|
|
29
|
+
}, {
|
|
30
|
+
modelValue: {},
|
|
31
|
+
modelModifiers: {}
|
|
32
|
+
}),
|
|
33
|
+
emits: ["update:modelValue"],
|
|
34
|
+
setup(o) {
|
|
35
|
+
let s = f(), b = d(o, "modelValue"), x = o, S = e(() => {
|
|
36
|
+
let e = b.value;
|
|
37
|
+
if (e !== void 0) return h(e) ? e.column : e;
|
|
38
|
+
}), C = e(() => {
|
|
39
|
+
let e = b.value;
|
|
40
|
+
return h(e) ? e.filter : void 0;
|
|
41
|
+
}), w = e(() => {
|
|
42
|
+
let e = S.value;
|
|
43
|
+
if (e) return x.options?.find((t) => g(t.ref, e, !0));
|
|
44
|
+
}), T = e(() => (w.value?.filters?.length ?? 0) > 0), E = e(() => {
|
|
45
|
+
let e = w.value?.filters;
|
|
46
|
+
return e ? [{
|
|
47
|
+
label: x.noFilterLabel,
|
|
48
|
+
value: null
|
|
49
|
+
}, ...e.map((e) => ({
|
|
50
|
+
label: e.label,
|
|
51
|
+
value: e.ref
|
|
52
|
+
}))] : [];
|
|
53
|
+
}), D = e(() => C.value ?? null);
|
|
54
|
+
function O(e, t) {
|
|
55
|
+
b.value = e === void 0 ? void 0 : m(e, t);
|
|
56
|
+
}
|
|
57
|
+
function k(e) {
|
|
58
|
+
O(e, void 0);
|
|
59
|
+
}
|
|
60
|
+
function A(e) {
|
|
61
|
+
let t = S.value;
|
|
62
|
+
t && O(t, e ?? void 0);
|
|
63
|
+
}
|
|
64
|
+
return (e, d) => (c(), r("div", y, [a(u(v), {
|
|
65
|
+
"model-value": S.value,
|
|
66
|
+
options: o.options,
|
|
67
|
+
label: o.label,
|
|
68
|
+
helper: o.helper,
|
|
69
|
+
"loading-options-helper": o.loadingOptionsHelper,
|
|
70
|
+
error: o.error,
|
|
71
|
+
placeholder: o.placeholder,
|
|
72
|
+
clearable: o.clearable,
|
|
73
|
+
required: o.required,
|
|
74
|
+
disabled: o.disabled,
|
|
75
|
+
"onUpdate:modelValue": k
|
|
76
|
+
}, i({ _: 2 }, [s.tooltip ? {
|
|
77
|
+
name: "tooltip",
|
|
78
|
+
fn: p(() => [l(e.$slots, "tooltip", {}, void 0, !0)]),
|
|
79
|
+
key: "0"
|
|
80
|
+
} : void 0]), 1032, [
|
|
81
|
+
"model-value",
|
|
82
|
+
"options",
|
|
83
|
+
"label",
|
|
84
|
+
"helper",
|
|
85
|
+
"loading-options-helper",
|
|
86
|
+
"error",
|
|
87
|
+
"placeholder",
|
|
88
|
+
"clearable",
|
|
89
|
+
"required",
|
|
90
|
+
"disabled"
|
|
91
|
+
]), T.value ? (c(), t(u(_), {
|
|
92
|
+
key: 0,
|
|
93
|
+
"model-value": D.value,
|
|
94
|
+
options: E.value,
|
|
95
|
+
label: o.filterLabel,
|
|
96
|
+
placeholder: o.filterPlaceholder,
|
|
97
|
+
disabled: o.disabled,
|
|
98
|
+
"onUpdate:modelValue": A
|
|
99
|
+
}, null, 8, [
|
|
100
|
+
"model-value",
|
|
101
|
+
"options",
|
|
102
|
+
"label",
|
|
103
|
+
"placeholder",
|
|
104
|
+
"disabled"
|
|
105
|
+
])) : n("", !0)]));
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
//#endregion
|
|
109
|
+
export { b as default };
|
|
110
|
+
|
|
111
|
+
//# sourceMappingURL=PlDatasetSelector.vue2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PlDatasetSelector.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/PlDatasetSelector/PlDatasetSelector.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Select a dataset and (optionally) a filter column, emitting a `PrimaryRef`.\n *\n * Behaves like {@link PlDropdownRef} when none of the offered datasets carry\n * filter options. When the selected dataset has compatible filters, a second\n * dropdown appears with the filters plus a \"No filter\" entry.\n *\n * Accepts `PrimaryRef | PlRef | undefined` as `modelValue` (a plain `PlRef`\n * is treated as an unfiltered dataset), but always emits `PrimaryRef`\n * (or `undefined` when cleared).\n */\nexport default {\n name: \"PlDatasetSelector\",\n};\n</script>\n\n<script lang=\"ts\" setup>\nimport type { DatasetOption, PlRef, PrimaryRef } from \"@platforma-sdk/model\";\nimport { createPrimaryRef, isPrimaryRef, plRefsEqual } from \"@platforma-sdk/model\";\nimport type { ListOption } from \"@milaboratories/uikit\";\nimport { PlDropdown, PlDropdownRef } from \"@milaboratories/uikit\";\nimport { computed } from \"vue\";\n\nconst slots = defineSlots<{\n tooltip?: () => unknown;\n}>();\n\n/**\n * v-model value. Accepts `PrimaryRef`, plain `PlRef` (treated as unfiltered),\n * or `undefined`. Writes always emit `PrimaryRef` or `undefined`.\n */\nconst model = defineModel<PrimaryRef | PlRef | undefined>();\n\nconst props = withDefaults(\n defineProps<{\n /** Available datasets, each optionally carrying compatible filter choices. */\n options?: Readonly<DatasetOption[]>;\n /** Label above the dataset dropdown. */\n label?: string;\n /** Helper text below the dataset dropdown (shown when there is no error). */\n helper?: string;\n /** Helper text shown while `options` is undefined (loading). */\n loadingOptionsHelper?: string;\n /** Error message displayed below the dataset dropdown. */\n error?: unknown;\n /** Placeholder when no dataset is selected. */\n placeholder?: string;\n /** Label above the filter dropdown. */\n filterLabel?: string;\n /** Placeholder for the filter dropdown. */\n filterPlaceholder?: string;\n /** Label of the \"no filter\" entry prepended to the filter options. */\n noFilterLabel?: string;\n /** Show a clear button on the dataset dropdown. */\n clearable?: boolean;\n /** Mark the dataset dropdown as required. */\n required?: boolean;\n /** Disable all interaction. */\n disabled?: boolean;\n }>(),\n {\n options: undefined,\n label: undefined,\n helper: undefined,\n loadingOptionsHelper: undefined,\n error: undefined,\n placeholder: \"...\",\n filterLabel: \"\",\n filterPlaceholder: \"...\",\n noFilterLabel: \"No filter\",\n clearable: false,\n required: false,\n disabled: false,\n },\n);\n\nconst selectedDataset = computed<PlRef | undefined>(() => {\n const v = model.value;\n if (v === undefined) return undefined;\n return isPrimaryRef(v) ? v.column : v;\n});\n\nconst selectedFilter = computed<PlRef | undefined>(() => {\n const v = model.value;\n return isPrimaryRef(v) ? v.filter : undefined;\n});\n\nconst currentDatasetOption = computed<DatasetOption | undefined>(() => {\n const dataset = selectedDataset.value;\n if (!dataset) return undefined;\n return props.options?.find((o) => plRefsEqual(o.ref, dataset, true));\n});\n\nconst hasFilters = computed(() => (currentDatasetOption.value?.filters?.length ?? 0) > 0);\n\n/**\n * Filter dropdown options. The first entry (`null`) is the \"No filter\" choice —\n * null distinguishes it from `undefined` (dropdown clear button, disabled here).\n */\nconst filterOptions = computed<ListOption<PlRef | null>[]>(() => {\n const filters = currentDatasetOption.value?.filters;\n if (!filters) return [];\n return [\n { label: props.noFilterLabel, value: null } as ListOption<PlRef | null>,\n ...filters.map((f) => ({ label: f.label, value: f.ref }) as ListOption<PlRef | null>),\n ];\n});\n\nconst filterValue = computed<PlRef | null>(() => selectedFilter.value ?? null);\n\nfunction emitValue(dataset: PlRef | undefined, filter: PlRef | undefined) {\n model.value = dataset === undefined ? undefined : createPrimaryRef(dataset, filter);\n}\n\nfunction onDatasetChange(dataset: PlRef | undefined) {\n emitValue(dataset, undefined);\n}\n\nfunction onFilterChange(value: PlRef | null | undefined) {\n const dataset = selectedDataset.value;\n if (!dataset) return;\n emitValue(dataset, value ?? undefined);\n}\n</script>\n\n<template>\n <div class=\"pl-dataset-selector\">\n <PlDropdownRef\n :model-value=\"selectedDataset\"\n :options=\"options\"\n :label=\"label\"\n :helper=\"helper\"\n :loading-options-helper=\"loadingOptionsHelper\"\n :error=\"error\"\n :placeholder=\"placeholder\"\n :clearable=\"clearable\"\n :required=\"required\"\n :disabled=\"disabled\"\n @update:model-value=\"onDatasetChange\"\n >\n <template v-if=\"slots.tooltip\" #tooltip>\n <slot name=\"tooltip\" />\n </template>\n </PlDropdownRef>\n <PlDropdown\n v-if=\"hasFilters\"\n :model-value=\"filterValue\"\n :options=\"filterOptions\"\n :label=\"filterLabel\"\n :placeholder=\"filterPlaceholder\"\n :disabled=\"disabled\"\n @update:model-value=\"onFilterChange\"\n />\n </div>\n</template>\n\n<style scoped>\n.pl-dataset-selector {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n</style>\n"],"mappings":";;;;;CAaE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAWR,IAAM,IAAQ,GAEV,EAME,IAAQ,EAA2C,GAAA,aAAE,EAErD,IAAQ,GA2CR,IAAkB,QAAkC;GACxD,IAAM,IAAI,EAAM;AACZ,aAAM,KAAA,EACV,QAAO,EAAa,EAAE,GAAG,EAAE,SAAS;IACpC,EAEI,IAAiB,QAAkC;GACvD,IAAM,IAAI,EAAM;AAChB,UAAO,EAAa,EAAE,GAAG,EAAE,SAAS,KAAA;IACpC,EAEI,IAAuB,QAA0C;GACrE,IAAM,IAAU,EAAgB;AAC3B,SACL,QAAO,EAAM,SAAS,MAAM,MAAM,EAAY,EAAE,KAAK,GAAS,GAAK,CAAC;IACpE,EAEI,IAAa,SAAgB,EAAqB,OAAO,SAAS,UAAU,KAAK,EAAE,EAMnF,IAAgB,QAA2C;GAC/D,IAAM,IAAU,EAAqB,OAAO;AAE5C,UADK,IACE,CACL;IAAE,OAAO,EAAM;IAAe,OAAO;IAAM,EAC3C,GAAG,EAAQ,KAAK,OAAO;IAAE,OAAO,EAAE;IAAO,OAAO,EAAE;IAAK,EAA8B,CACtF,GAJoB,EAAE;IAKvB,EAEI,IAAc,QAA6B,EAAe,SAAS,KAAK;EAE9E,SAAS,EAAU,GAA4B,GAA2B;AACxE,KAAM,QAAQ,MAAY,KAAA,IAAY,KAAA,IAAY,EAAiB,GAAS,EAAO;;EAGrF,SAAS,EAAgB,GAA4B;AACnD,KAAU,GAAS,KAAA,EAAU;;EAG/B,SAAS,EAAe,GAAiC;GACvD,IAAM,IAAU,EAAgB;AAC3B,QACL,EAAU,GAAS,KAAS,KAAA,EAAU;;yBAKtC,EA2BM,OA3BN,GA2BM,CA1BJ,EAgBgB,EAAA,EAAA,EAAA;GAfb,eAAa,EAAA;GACb,SAAS,EAAA;GACT,OAAO,EAAA;GACP,QAAQ,EAAA;GACR,0BAAwB,EAAA;GACxB,OAAO,EAAA;GACP,aAAa,EAAA;GACb,WAAW,EAAA;GACX,UAAU,EAAA;GACV,UAAU,EAAA;GACV,uBAAoB;kBAEL,EAAM,UAAA;SAAU;eACP,CAAvB,EAAuB,EAAA,QAAA,WAAA,EAAA,EAAA,KAAA,GAAA,GAAA,CAAA,CAAA;;;;;;;;;;;;;MAInB,EAAA,SAAA,GAAA,EADR,EAQE,EAAA,EAAA,EAAA;;GANC,eAAa,EAAA;GACb,SAAS,EAAA;GACT,OAAO,EAAA;GACP,aAAa,EAAA;GACb,UAAU,EAAA;GACV,uBAAoB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PlDatasetSelector.jsdomtest.d.ts","sourceRoot":"","sources":["../../../../src/components/PlDatasetSelector/__tests__/PlDatasetSelector.jsdomtest.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/PlDatasetSelector/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,yBAAyB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import "./PlDatasetSelector.js";
|
package/dist/index.js
CHANGED
|
@@ -9,11 +9,11 @@ import x from "./components/PlAgGridColumnManager/PlAgGridColumnManager.js";
|
|
|
9
9
|
import S from "./components/PlAdvancedFilter/PlAdvancedFilter.js";
|
|
10
10
|
import { PlAdvancedFilterSupportedFilters as C } from "./components/PlAdvancedFilter/index.js";
|
|
11
11
|
import w from "./components/PlTableFilters/PlTableFiltersV2.js";
|
|
12
|
-
import { DeferredCircular as T, ensureNodeVisible as
|
|
13
|
-
import
|
|
14
|
-
import
|
|
15
|
-
import { defaultMainMenuItems as
|
|
16
|
-
import
|
|
12
|
+
import { DeferredCircular as T, ensureNodeVisible as E } from "./components/PlAgDataTable/sources/focus-row.js";
|
|
13
|
+
import D from "./components/PlAgColumnHeader/PlAgColumnHeader.js";
|
|
14
|
+
import O from "./components/PlAgTextAndButtonCell/PlAgTextAndButtonCell.js";
|
|
15
|
+
import { defaultMainMenuItems as k } from "./components/PlAgDataTable/sources/menu-items.js";
|
|
16
|
+
import ee from "./components/PlAgDataTable/PlAgOverlayLoading.js";
|
|
17
17
|
import A from "./components/PlAgDataTable/PlAgOverlayNoRows.js";
|
|
18
18
|
import { AgGridTheme as j } from "./AgGridVue/AgGridTheme.js";
|
|
19
19
|
import M from "./components/PlAgDataTable/PlAgDataTableV2.js";
|
|
@@ -29,17 +29,18 @@ import { deselectAll as V, getSelectedRowsCount as H, getTotalRowsCount as U, is
|
|
|
29
29
|
import K from "./components/PlAnnotations/components/PlAnnotations.js";
|
|
30
30
|
import q from "./components/PlAnnotations/components/PlAnnotationsModal.js";
|
|
31
31
|
import J from "./components/PlBtnExportArchive/PlBtnExportArchive.js";
|
|
32
|
-
import
|
|
33
|
-
import {
|
|
34
|
-
import {
|
|
35
|
-
import {
|
|
36
|
-
import {
|
|
37
|
-
import {
|
|
32
|
+
import Y from "./components/PlDatasetSelector/PlDatasetSelector.js";
|
|
33
|
+
import { usePlugin as X } from "./usePlugin.js";
|
|
34
|
+
import { defineStore as Z } from "./defineStore.js";
|
|
35
|
+
import { activateAgGrid as Q } from "./composition/AgGrid/index.js";
|
|
36
|
+
import { objectHash as $ } from "./objectHash.js";
|
|
37
|
+
import { computedResult as te } from "./computedResult.js";
|
|
38
|
+
import { ReactiveFileContent as ne } from "./composition/fileContent.js";
|
|
38
39
|
import "./lib.js";
|
|
39
|
-
import { setAutoFreeze as
|
|
40
|
+
import { setAutoFreeze as re } from "immer";
|
|
40
41
|
export * from "@milaboratories/uikit";
|
|
41
|
-
|
|
42
|
+
re(!1);
|
|
42
43
|
//#endregion
|
|
43
|
-
export { j as AgGridTheme, g as BlockLayout, T as DeferredCircular, e as MultiError, S as PlAdvancedFilterComponent, C as PlAdvancedFilterSupportedFilters, I as PlAgCellFile, P as PlAgCellProgress, z as PlAgCellStatusTag, R as PlAgChartHistogramCell, L as PlAgChartStackedBarCell,
|
|
44
|
+
export { j as AgGridTheme, g as BlockLayout, T as DeferredCircular, e as MultiError, S as PlAdvancedFilterComponent, C as PlAdvancedFilterSupportedFilters, I as PlAgCellFile, P as PlAgCellProgress, z as PlAgCellStatusTag, R as PlAgChartHistogramCell, L as PlAgChartStackedBarCell, D as PlAgColumnHeader, _ as PlAgCsvExporter, v as PlAgDataTableRowNumberColId, M as PlAgDataTableV2, x as PlAgGridColumnManager, ee as PlAgOverlayLoading, A as PlAgOverlayNoRows, O as PlAgTextAndButtonCell, K as PlAnnotations, q as PlAnnotationsModal, J as PlBtnExportArchive, M as PlDataTableV2, Y as PlDatasetSelector, w as PlTableFiltersV2, ne as ReactiveFileContent, t as UnresolvedError, Q as activateAgGrid, y as autoSizeRowNumberColumn, te as computedResult, F as createAgGridColDef, u as createModel, k as defaultMainMenuItems, d as defineApp, f as defineAppV3, Z as defineStore, V as deselectAll, n as ensureError, E as ensureNodeVisible, r as ensureOutputHasStableFlag, i as formatZodError, H as getSelectedRowsCount, U as getTotalRowsCount, a as identity, o as isDefined, W as isSelectionEnabled, s as isZodError, b as makeRowNumberColDef, $ as objectHash, p as pluginDataKey, G as selectAll, c as unwrapOutput, B as useAgGridOptions, m as useFeatureFlags, N as usePlDataTableSettingsV2, X as usePlugin, h as useSdkPlugin, l as wrapOptionalResult };
|
|
44
45
|
|
|
45
46
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import { setAutoFreeze } from \"immer\";\n\nsetAutoFreeze(false);\n\nexport * from \"./lib\";\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import { setAutoFreeze } from \"immer\";\n\nsetAutoFreeze(false);\n\nexport * from \"./lib\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,GAAc,GAAM"}
|
package/dist/lib.d.ts
CHANGED
|
@@ -18,6 +18,7 @@ export * from './components/PlTableFilters';
|
|
|
18
18
|
export * from './components/PlAnnotations';
|
|
19
19
|
export * from './components/PlBtnExportArchive';
|
|
20
20
|
export * from './components/PlAdvancedFilter';
|
|
21
|
+
export * from './components/PlDatasetSelector';
|
|
21
22
|
export * from './defineApp';
|
|
22
23
|
export { usePlugin } from './usePlugin';
|
|
23
24
|
export type { PluginState } from './usePlugin';
|
package/dist/lib.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lib.d.ts","sourceRoot":"","sources":["../src/lib.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAE1B,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,8BAA8B,CAAC;AACtE,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,gDAAgD,CAAC;AAC5F,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,mDAAmD,CAAC;AAClG,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,kDAAkD,CAAC;AAEhG,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,cAAc,aAAa,CAAC;AAE5B,cAAc,+BAA+B,CAAC;AAE9C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,qCAAqC,CAAC;AACpD,cAAc,sCAAsC,CAAC;AAErD,cAAc,4BAA4B,CAAC;AAE3C,cAAc,8BAA8B,CAAC;AAE7C,cAAc,oCAAoC,CAAC;AAEnD,cAAc,oCAAoC,CAAC;AAEnD,cAAc,6BAA6B,CAAC;AAE5C,cAAc,4BAA4B,CAAC;AAE3C,cAAc,iCAAiC,CAAC;AAEhD,cAAc,+BAA+B,CAAC;AAE9C,cAAc,aAAa,CAAC;AAE5B,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,YAAY,EACV,YAAY,EACZ,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,sBAAsB,CAAC;AAE9B,cAAc,eAAe,CAAC;AAE9B,cAAc,SAAS,CAAC;AAExB,cAAc,eAAe,CAAC;AAE9B,cAAc,sBAAsB,CAAC;AAErC,cAAc,SAAS,CAAC;AAExB,cAAc,cAAc,CAAC;AAE7B,cAAc,kBAAkB,CAAC;AAEjC,cAAc,2BAA2B,CAAC;AAE1C,cAAc,uBAAuB,CAAC;AAEtC,mBAAmB,uBAAuB,CAAC"}
|
|
1
|
+
{"version":3,"file":"lib.d.ts","sourceRoot":"","sources":["../src/lib.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAE1B,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,8BAA8B,CAAC;AACtE,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,gDAAgD,CAAC;AAC5F,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,mDAAmD,CAAC;AAClG,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,kDAAkD,CAAC;AAEhG,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,cAAc,aAAa,CAAC;AAE5B,cAAc,+BAA+B,CAAC;AAE9C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,qCAAqC,CAAC;AACpD,cAAc,sCAAsC,CAAC;AAErD,cAAc,4BAA4B,CAAC;AAE3C,cAAc,8BAA8B,CAAC;AAE7C,cAAc,oCAAoC,CAAC;AAEnD,cAAc,oCAAoC,CAAC;AAEnD,cAAc,6BAA6B,CAAC;AAE5C,cAAc,4BAA4B,CAAC;AAE3C,cAAc,iCAAiC,CAAC;AAEhD,cAAc,+BAA+B,CAAC;AAE9C,cAAc,gCAAgC,CAAC;AAE/C,cAAc,aAAa,CAAC;AAE5B,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,YAAY,EACV,YAAY,EACZ,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,sBAAsB,CAAC;AAE9B,cAAc,eAAe,CAAC;AAE9B,cAAc,SAAS,CAAC;AAExB,cAAc,eAAe,CAAC;AAE9B,cAAc,sBAAsB,CAAC;AAErC,cAAc,SAAS,CAAC;AAExB,cAAc,cAAc,CAAC;AAE7B,cAAc,kBAAkB,CAAC;AAEjC,cAAc,2BAA2B,CAAC;AAE1C,cAAc,uBAAuB,CAAC;AAEtC,mBAAmB,uBAAuB,CAAC"}
|
package/dist/lib.js
CHANGED
|
@@ -44,6 +44,8 @@ import "./components/PlAnnotations/components/PlAnnotationsModal.js";
|
|
|
44
44
|
import "./components/PlAnnotations/index.js";
|
|
45
45
|
import "./components/PlBtnExportArchive/PlBtnExportArchive.js";
|
|
46
46
|
import "./components/PlBtnExportArchive/index.js";
|
|
47
|
+
import "./components/PlDatasetSelector/PlDatasetSelector.js";
|
|
48
|
+
import "./components/PlDatasetSelector/index.js";
|
|
47
49
|
import "./usePlugin.js";
|
|
48
50
|
import "./defineStore.js";
|
|
49
51
|
import "./composition/AgGrid/index.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@platforma-sdk/ui-vue",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.67.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"exports": {
|
|
@@ -26,10 +26,10 @@
|
|
|
26
26
|
"lru-cache": "^11.2.2",
|
|
27
27
|
"vue": "^3.5.24",
|
|
28
28
|
"zod": "~3.25.76",
|
|
29
|
-
"@milaboratories/
|
|
30
|
-
"@milaboratories/
|
|
31
|
-
"@
|
|
32
|
-
"@
|
|
29
|
+
"@milaboratories/pf-spec-driver": "1.3.3",
|
|
30
|
+
"@milaboratories/pl-model-common": "1.35.0",
|
|
31
|
+
"@platforma-sdk/model": "1.67.0",
|
|
32
|
+
"@milaboratories/uikit": "2.12.9"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@faker-js/faker": "^9.2.0",
|
|
@@ -37,16 +37,18 @@
|
|
|
37
37
|
"@vitest/coverage-istanbul": "^4.1.3",
|
|
38
38
|
"@vue/test-utils": "^2.4.6",
|
|
39
39
|
"fast-json-patch": "^3.1.1",
|
|
40
|
+
"jsdom": "^25.0.1",
|
|
41
|
+
"resize-observer-polyfill": "^1.5.1",
|
|
40
42
|
"rollup-plugin-sourcemaps2": "^0.5.2",
|
|
41
43
|
"sass": "~1.83.4",
|
|
42
44
|
"semver": "^7.7.2",
|
|
43
45
|
"typescript": "~5.9.3",
|
|
44
46
|
"vite": "^8.0.6",
|
|
45
47
|
"vitest": "^4.1.3",
|
|
46
|
-
"@milaboratories/ts-builder": "1.3.2",
|
|
47
48
|
"@milaboratories/helpers": "1.14.1",
|
|
49
|
+
"@milaboratories/build-configs": "2.0.0",
|
|
48
50
|
"@milaboratories/ts-configs": "1.2.3",
|
|
49
|
-
"@milaboratories/
|
|
51
|
+
"@milaboratories/ts-builder": "1.3.2"
|
|
50
52
|
},
|
|
51
53
|
"scripts": {
|
|
52
54
|
"dev": "ts-builder serve --target browser-lib",
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import ResizeObserver from "resize-observer-polyfill";
|
|
2
|
+
globalThis.ResizeObserver = ResizeObserver;
|
|
3
|
+
|
|
4
|
+
// CSS.paintWorklet is not available in jsdom — uikit's PlPlaceholder
|
|
5
|
+
// accesses it at module load time.
|
|
6
|
+
if (typeof globalThis.CSS === "undefined") {
|
|
7
|
+
(globalThis as Record<string, unknown>).CSS = { paintWorklet: { addModule: () => {} } };
|
|
8
|
+
} else if (!("paintWorklet" in globalThis.CSS)) {
|
|
9
|
+
(globalThis.CSS as Record<string, unknown>).paintWorklet = { addModule: () => {} };
|
|
10
|
+
}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* Select a dataset and (optionally) a filter column, emitting a `PrimaryRef`.
|
|
4
|
+
*
|
|
5
|
+
* Behaves like {@link PlDropdownRef} when none of the offered datasets carry
|
|
6
|
+
* filter options. When the selected dataset has compatible filters, a second
|
|
7
|
+
* dropdown appears with the filters plus a "No filter" entry.
|
|
8
|
+
*
|
|
9
|
+
* Accepts `PrimaryRef | PlRef | undefined` as `modelValue` (a plain `PlRef`
|
|
10
|
+
* is treated as an unfiltered dataset), but always emits `PrimaryRef`
|
|
11
|
+
* (or `undefined` when cleared).
|
|
12
|
+
*/
|
|
13
|
+
export default {
|
|
14
|
+
name: "PlDatasetSelector",
|
|
15
|
+
};
|
|
16
|
+
</script>
|
|
17
|
+
|
|
18
|
+
<script lang="ts" setup>
|
|
19
|
+
import type { DatasetOption, PlRef, PrimaryRef } from "@platforma-sdk/model";
|
|
20
|
+
import { createPrimaryRef, isPrimaryRef, plRefsEqual } from "@platforma-sdk/model";
|
|
21
|
+
import type { ListOption } from "@milaboratories/uikit";
|
|
22
|
+
import { PlDropdown, PlDropdownRef } from "@milaboratories/uikit";
|
|
23
|
+
import { computed } from "vue";
|
|
24
|
+
|
|
25
|
+
const slots = defineSlots<{
|
|
26
|
+
tooltip?: () => unknown;
|
|
27
|
+
}>();
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* v-model value. Accepts `PrimaryRef`, plain `PlRef` (treated as unfiltered),
|
|
31
|
+
* or `undefined`. Writes always emit `PrimaryRef` or `undefined`.
|
|
32
|
+
*/
|
|
33
|
+
const model = defineModel<PrimaryRef | PlRef | undefined>();
|
|
34
|
+
|
|
35
|
+
const props = withDefaults(
|
|
36
|
+
defineProps<{
|
|
37
|
+
/** Available datasets, each optionally carrying compatible filter choices. */
|
|
38
|
+
options?: Readonly<DatasetOption[]>;
|
|
39
|
+
/** Label above the dataset dropdown. */
|
|
40
|
+
label?: string;
|
|
41
|
+
/** Helper text below the dataset dropdown (shown when there is no error). */
|
|
42
|
+
helper?: string;
|
|
43
|
+
/** Helper text shown while `options` is undefined (loading). */
|
|
44
|
+
loadingOptionsHelper?: string;
|
|
45
|
+
/** Error message displayed below the dataset dropdown. */
|
|
46
|
+
error?: unknown;
|
|
47
|
+
/** Placeholder when no dataset is selected. */
|
|
48
|
+
placeholder?: string;
|
|
49
|
+
/** Label above the filter dropdown. */
|
|
50
|
+
filterLabel?: string;
|
|
51
|
+
/** Placeholder for the filter dropdown. */
|
|
52
|
+
filterPlaceholder?: string;
|
|
53
|
+
/** Label of the "no filter" entry prepended to the filter options. */
|
|
54
|
+
noFilterLabel?: string;
|
|
55
|
+
/** Show a clear button on the dataset dropdown. */
|
|
56
|
+
clearable?: boolean;
|
|
57
|
+
/** Mark the dataset dropdown as required. */
|
|
58
|
+
required?: boolean;
|
|
59
|
+
/** Disable all interaction. */
|
|
60
|
+
disabled?: boolean;
|
|
61
|
+
}>(),
|
|
62
|
+
{
|
|
63
|
+
options: undefined,
|
|
64
|
+
label: undefined,
|
|
65
|
+
helper: undefined,
|
|
66
|
+
loadingOptionsHelper: undefined,
|
|
67
|
+
error: undefined,
|
|
68
|
+
placeholder: "...",
|
|
69
|
+
filterLabel: "",
|
|
70
|
+
filterPlaceholder: "...",
|
|
71
|
+
noFilterLabel: "No filter",
|
|
72
|
+
clearable: false,
|
|
73
|
+
required: false,
|
|
74
|
+
disabled: false,
|
|
75
|
+
},
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
const selectedDataset = computed<PlRef | undefined>(() => {
|
|
79
|
+
const v = model.value;
|
|
80
|
+
if (v === undefined) return undefined;
|
|
81
|
+
return isPrimaryRef(v) ? v.column : v;
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
const selectedFilter = computed<PlRef | undefined>(() => {
|
|
85
|
+
const v = model.value;
|
|
86
|
+
return isPrimaryRef(v) ? v.filter : undefined;
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
const currentDatasetOption = computed<DatasetOption | undefined>(() => {
|
|
90
|
+
const dataset = selectedDataset.value;
|
|
91
|
+
if (!dataset) return undefined;
|
|
92
|
+
return props.options?.find((o) => plRefsEqual(o.ref, dataset, true));
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
const hasFilters = computed(() => (currentDatasetOption.value?.filters?.length ?? 0) > 0);
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Filter dropdown options. The first entry (`null`) is the "No filter" choice —
|
|
99
|
+
* null distinguishes it from `undefined` (dropdown clear button, disabled here).
|
|
100
|
+
*/
|
|
101
|
+
const filterOptions = computed<ListOption<PlRef | null>[]>(() => {
|
|
102
|
+
const filters = currentDatasetOption.value?.filters;
|
|
103
|
+
if (!filters) return [];
|
|
104
|
+
return [
|
|
105
|
+
{ label: props.noFilterLabel, value: null } as ListOption<PlRef | null>,
|
|
106
|
+
...filters.map((f) => ({ label: f.label, value: f.ref }) as ListOption<PlRef | null>),
|
|
107
|
+
];
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
const filterValue = computed<PlRef | null>(() => selectedFilter.value ?? null);
|
|
111
|
+
|
|
112
|
+
function emitValue(dataset: PlRef | undefined, filter: PlRef | undefined) {
|
|
113
|
+
model.value = dataset === undefined ? undefined : createPrimaryRef(dataset, filter);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function onDatasetChange(dataset: PlRef | undefined) {
|
|
117
|
+
emitValue(dataset, undefined);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function onFilterChange(value: PlRef | null | undefined) {
|
|
121
|
+
const dataset = selectedDataset.value;
|
|
122
|
+
if (!dataset) return;
|
|
123
|
+
emitValue(dataset, value ?? undefined);
|
|
124
|
+
}
|
|
125
|
+
</script>
|
|
126
|
+
|
|
127
|
+
<template>
|
|
128
|
+
<div class="pl-dataset-selector">
|
|
129
|
+
<PlDropdownRef
|
|
130
|
+
:model-value="selectedDataset"
|
|
131
|
+
:options="options"
|
|
132
|
+
:label="label"
|
|
133
|
+
:helper="helper"
|
|
134
|
+
:loading-options-helper="loadingOptionsHelper"
|
|
135
|
+
:error="error"
|
|
136
|
+
:placeholder="placeholder"
|
|
137
|
+
:clearable="clearable"
|
|
138
|
+
:required="required"
|
|
139
|
+
:disabled="disabled"
|
|
140
|
+
@update:model-value="onDatasetChange"
|
|
141
|
+
>
|
|
142
|
+
<template v-if="slots.tooltip" #tooltip>
|
|
143
|
+
<slot name="tooltip" />
|
|
144
|
+
</template>
|
|
145
|
+
</PlDropdownRef>
|
|
146
|
+
<PlDropdown
|
|
147
|
+
v-if="hasFilters"
|
|
148
|
+
:model-value="filterValue"
|
|
149
|
+
:options="filterOptions"
|
|
150
|
+
:label="filterLabel"
|
|
151
|
+
:placeholder="filterPlaceholder"
|
|
152
|
+
:disabled="disabled"
|
|
153
|
+
@update:model-value="onFilterChange"
|
|
154
|
+
/>
|
|
155
|
+
</div>
|
|
156
|
+
</template>
|
|
157
|
+
|
|
158
|
+
<style scoped>
|
|
159
|
+
.pl-dataset-selector {
|
|
160
|
+
display: flex;
|
|
161
|
+
flex-direction: column;
|
|
162
|
+
gap: 12px;
|
|
163
|
+
}
|
|
164
|
+
</style>
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
import { flushPromises, mount } from "@vue/test-utils";
|
|
2
|
+
import type { DatasetOption, PrimaryRef } from "@platforma-sdk/model";
|
|
3
|
+
import { createPlRef, createPrimaryRef } from "@platforma-sdk/model";
|
|
4
|
+
import { describe, expect, it } from "vitest";
|
|
5
|
+
import PlDatasetSelector from "../PlDatasetSelector.vue";
|
|
6
|
+
|
|
7
|
+
const datasetA = createPlRef("1", "out-a", true);
|
|
8
|
+
const datasetB = createPlRef("2", "out-b", true);
|
|
9
|
+
const filterA1 = createPlRef("1", "filter-a1");
|
|
10
|
+
const filterA2 = createPlRef("1", "filter-a2");
|
|
11
|
+
|
|
12
|
+
const optionsWithFilters: DatasetOption[] = [
|
|
13
|
+
{
|
|
14
|
+
label: "Dataset A",
|
|
15
|
+
ref: datasetA,
|
|
16
|
+
filters: [
|
|
17
|
+
{ label: "Top 1000", ref: filterA1 },
|
|
18
|
+
{ label: "High quality", ref: filterA2 },
|
|
19
|
+
],
|
|
20
|
+
},
|
|
21
|
+
// Dataset B has no filters — filter dropdown must stay hidden.
|
|
22
|
+
{ label: "Dataset B", ref: datasetB },
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
const datasetC = createPlRef("3", "out-c", true);
|
|
26
|
+
|
|
27
|
+
const optionsNoFilters: DatasetOption[] = [{ label: "Dataset B", ref: datasetB }];
|
|
28
|
+
|
|
29
|
+
const optionsWithEmptyFilters: DatasetOption[] = [
|
|
30
|
+
{ label: "Dataset C", ref: datasetC, filters: [] },
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
async function pickOption(index: number) {
|
|
34
|
+
const options = [...document.body.querySelectorAll(".dropdown-list-item")] as HTMLElement[];
|
|
35
|
+
options[index].click();
|
|
36
|
+
await flushPromises();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
describe("PlDatasetSelector", () => {
|
|
40
|
+
it("renders a single dropdown when no dataset has filters", async () => {
|
|
41
|
+
const wrapper = mount(PlDatasetSelector, {
|
|
42
|
+
props: { modelValue: undefined, options: optionsNoFilters },
|
|
43
|
+
attachTo: document.body,
|
|
44
|
+
});
|
|
45
|
+
await flushPromises();
|
|
46
|
+
|
|
47
|
+
const selector = wrapper.find(".pl-dataset-selector");
|
|
48
|
+
expect(selector.exists()).toBe(true);
|
|
49
|
+
// Only PlDropdownRef is rendered — no filter dropdown.
|
|
50
|
+
expect(selector.element.children.length).toBe(1);
|
|
51
|
+
wrapper.unmount();
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it("shows the filter dropdown when the selected dataset has filters", async () => {
|
|
55
|
+
const wrapper = mount(PlDatasetSelector, {
|
|
56
|
+
props: { modelValue: createPrimaryRef(datasetA), options: optionsWithFilters },
|
|
57
|
+
attachTo: document.body,
|
|
58
|
+
});
|
|
59
|
+
await flushPromises();
|
|
60
|
+
|
|
61
|
+
expect(wrapper.find(".pl-dataset-selector").element.children.length).toBe(2);
|
|
62
|
+
wrapper.unmount();
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it("hides the filter dropdown when the selected dataset has no filters", async () => {
|
|
66
|
+
const wrapper = mount(PlDatasetSelector, {
|
|
67
|
+
props: { modelValue: createPrimaryRef(datasetB), options: optionsWithFilters },
|
|
68
|
+
attachTo: document.body,
|
|
69
|
+
});
|
|
70
|
+
await flushPromises();
|
|
71
|
+
|
|
72
|
+
expect(wrapper.find(".pl-dataset-selector").element.children.length).toBe(1);
|
|
73
|
+
wrapper.unmount();
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it("emits PrimaryRef with filter: undefined when dataset changes", async () => {
|
|
77
|
+
const wrapper = mount(PlDatasetSelector, {
|
|
78
|
+
props: {
|
|
79
|
+
modelValue: createPrimaryRef(datasetA, filterA1),
|
|
80
|
+
options: optionsWithFilters,
|
|
81
|
+
"onUpdate:modelValue": (e) => wrapper.setProps({ modelValue: e }),
|
|
82
|
+
},
|
|
83
|
+
attachTo: document.body,
|
|
84
|
+
});
|
|
85
|
+
await flushPromises();
|
|
86
|
+
|
|
87
|
+
// Open the dataset dropdown (the first input — dataset comes first).
|
|
88
|
+
const inputs = wrapper.findAll("input");
|
|
89
|
+
await inputs[0].trigger("focus");
|
|
90
|
+
|
|
91
|
+
// Dataset A is already selected (index 0); pick Dataset B (index 1).
|
|
92
|
+
await pickOption(1);
|
|
93
|
+
|
|
94
|
+
const emitted = wrapper.emitted("update:modelValue");
|
|
95
|
+
expect(emitted).toBeDefined();
|
|
96
|
+
const last = emitted![emitted!.length - 1][0] as PrimaryRef;
|
|
97
|
+
expect(last).toEqual({ __isPrimaryRef: "v1", column: datasetB });
|
|
98
|
+
wrapper.unmount();
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it("emits PrimaryRef with filter set when a filter is picked", async () => {
|
|
102
|
+
const wrapper = mount(PlDatasetSelector, {
|
|
103
|
+
props: {
|
|
104
|
+
modelValue: createPrimaryRef(datasetA),
|
|
105
|
+
options: optionsWithFilters,
|
|
106
|
+
"onUpdate:modelValue": (e) => wrapper.setProps({ modelValue: e }),
|
|
107
|
+
},
|
|
108
|
+
attachTo: document.body,
|
|
109
|
+
});
|
|
110
|
+
await flushPromises();
|
|
111
|
+
|
|
112
|
+
// Open the filter dropdown — it's the second input in the component.
|
|
113
|
+
const inputs = wrapper.findAll("input");
|
|
114
|
+
expect(inputs.length).toBe(2);
|
|
115
|
+
await inputs[1].trigger("focus");
|
|
116
|
+
|
|
117
|
+
// Options are: [No filter, Top 1000, High quality]. Pick "Top 1000" (index 1).
|
|
118
|
+
await pickOption(1);
|
|
119
|
+
|
|
120
|
+
const emitted = wrapper.emitted("update:modelValue");
|
|
121
|
+
expect(emitted).toBeDefined();
|
|
122
|
+
const last = emitted![emitted!.length - 1][0] as PrimaryRef;
|
|
123
|
+
expect(last).toEqual({ __isPrimaryRef: "v1", column: datasetA, filter: filterA1 });
|
|
124
|
+
wrapper.unmount();
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it("emits PrimaryRef with filter: undefined when 'No filter' is picked", async () => {
|
|
128
|
+
const wrapper = mount(PlDatasetSelector, {
|
|
129
|
+
props: {
|
|
130
|
+
modelValue: createPrimaryRef(datasetA, filterA1),
|
|
131
|
+
options: optionsWithFilters,
|
|
132
|
+
"onUpdate:modelValue": (e) => wrapper.setProps({ modelValue: e }),
|
|
133
|
+
},
|
|
134
|
+
attachTo: document.body,
|
|
135
|
+
});
|
|
136
|
+
await flushPromises();
|
|
137
|
+
|
|
138
|
+
const inputs = wrapper.findAll("input");
|
|
139
|
+
await inputs[1].trigger("focus");
|
|
140
|
+
// Pick "No filter" (index 0).
|
|
141
|
+
await pickOption(0);
|
|
142
|
+
|
|
143
|
+
const emitted = wrapper.emitted("update:modelValue");
|
|
144
|
+
expect(emitted).toBeDefined();
|
|
145
|
+
const last = emitted![emitted!.length - 1][0] as PrimaryRef;
|
|
146
|
+
expect(last).toEqual({ __isPrimaryRef: "v1", column: datasetA });
|
|
147
|
+
expect("filter" in last).toBe(false);
|
|
148
|
+
wrapper.unmount();
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
it("accepts plain PlRef as modelValue for backward compat (filterless dataset)", async () => {
|
|
152
|
+
const wrapper = mount(PlDatasetSelector, {
|
|
153
|
+
props: { modelValue: datasetB, options: optionsWithFilters },
|
|
154
|
+
attachTo: document.body,
|
|
155
|
+
});
|
|
156
|
+
await flushPromises();
|
|
157
|
+
|
|
158
|
+
expect(wrapper.find(".pl-dataset-selector").element.children.length).toBe(1);
|
|
159
|
+
wrapper.unmount();
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
it("accepts plain PlRef as modelValue for backward compat (dataset with filters)", async () => {
|
|
163
|
+
const wrapper = mount(PlDatasetSelector, {
|
|
164
|
+
props: { modelValue: datasetA, options: optionsWithFilters },
|
|
165
|
+
attachTo: document.body,
|
|
166
|
+
});
|
|
167
|
+
await flushPromises();
|
|
168
|
+
|
|
169
|
+
// PlRef matching dataset A — filter dropdown should appear since A has filters.
|
|
170
|
+
expect(wrapper.find(".pl-dataset-selector").element.children.length).toBe(2);
|
|
171
|
+
wrapper.unmount();
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
it("hides filter dropdown when dataset has filters: [] (empty array)", async () => {
|
|
175
|
+
const wrapper = mount(PlDatasetSelector, {
|
|
176
|
+
props: { modelValue: createPrimaryRef(datasetC), options: optionsWithEmptyFilters },
|
|
177
|
+
attachTo: document.body,
|
|
178
|
+
});
|
|
179
|
+
await flushPromises();
|
|
180
|
+
|
|
181
|
+
expect(wrapper.find(".pl-dataset-selector").element.children.length).toBe(1);
|
|
182
|
+
wrapper.unmount();
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
it("filter dropdown defaults to 'No filter' when dataset has filters but none selected", async () => {
|
|
186
|
+
const wrapper = mount(PlDatasetSelector, {
|
|
187
|
+
props: {
|
|
188
|
+
modelValue: createPrimaryRef(datasetA),
|
|
189
|
+
options: optionsWithFilters,
|
|
190
|
+
"onUpdate:modelValue": (e) => wrapper.setProps({ modelValue: e }),
|
|
191
|
+
},
|
|
192
|
+
attachTo: document.body,
|
|
193
|
+
});
|
|
194
|
+
await flushPromises();
|
|
195
|
+
|
|
196
|
+
// No emission on mount — the component does not auto-select a filter.
|
|
197
|
+
expect(wrapper.emitted("update:modelValue")).toBeUndefined();
|
|
198
|
+
|
|
199
|
+
// Filter dropdown is visible.
|
|
200
|
+
const inputs = wrapper.findAll("input");
|
|
201
|
+
expect(inputs.length).toBe(2);
|
|
202
|
+
|
|
203
|
+
// Open filter dropdown and verify "No filter" is the first option.
|
|
204
|
+
await inputs[1].trigger("focus");
|
|
205
|
+
const items = document.body.querySelectorAll(".dropdown-list-item");
|
|
206
|
+
expect(items.length).toBe(3); // No filter, Top 1000, High quality
|
|
207
|
+
expect(items[0].textContent).toContain("No filter");
|
|
208
|
+
wrapper.unmount();
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
it("emits PrimaryRef without filter key when selecting a filterless dataset", async () => {
|
|
212
|
+
const wrapper = mount(PlDatasetSelector, {
|
|
213
|
+
props: {
|
|
214
|
+
modelValue: undefined,
|
|
215
|
+
options: optionsNoFilters,
|
|
216
|
+
"onUpdate:modelValue": (e) => wrapper.setProps({ modelValue: e }),
|
|
217
|
+
},
|
|
218
|
+
attachTo: document.body,
|
|
219
|
+
});
|
|
220
|
+
await flushPromises();
|
|
221
|
+
|
|
222
|
+
const inputs = wrapper.findAll("input");
|
|
223
|
+
await inputs[0].trigger("focus");
|
|
224
|
+
await pickOption(0);
|
|
225
|
+
|
|
226
|
+
const emitted = wrapper.emitted("update:modelValue");
|
|
227
|
+
expect(emitted).toBeDefined();
|
|
228
|
+
const last = emitted![emitted!.length - 1][0] as PrimaryRef;
|
|
229
|
+
expect(last).toEqual({ __isPrimaryRef: "v1", column: datasetB });
|
|
230
|
+
expect("filter" in last).toBe(false);
|
|
231
|
+
wrapper.unmount();
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
it("emits undefined when cleared via the dataset dropdown", async () => {
|
|
235
|
+
const wrapper = mount(PlDatasetSelector, {
|
|
236
|
+
props: {
|
|
237
|
+
modelValue: createPrimaryRef(datasetA, filterA1),
|
|
238
|
+
options: optionsWithFilters,
|
|
239
|
+
clearable: true,
|
|
240
|
+
"onUpdate:modelValue": (e) => wrapper.setProps({ modelValue: e }),
|
|
241
|
+
},
|
|
242
|
+
attachTo: document.body,
|
|
243
|
+
});
|
|
244
|
+
await flushPromises();
|
|
245
|
+
|
|
246
|
+
// PlDropdown's clear button carries the ".clear" class.
|
|
247
|
+
const clearBtn = wrapper.find(".clear");
|
|
248
|
+
expect(clearBtn.exists()).toBe(true);
|
|
249
|
+
await clearBtn.trigger("click");
|
|
250
|
+
|
|
251
|
+
const emitted = wrapper.emitted("update:modelValue");
|
|
252
|
+
expect(emitted).toBeDefined();
|
|
253
|
+
const last = emitted![emitted!.length - 1][0];
|
|
254
|
+
expect(last).toBeUndefined();
|
|
255
|
+
wrapper.unmount();
|
|
256
|
+
});
|
|
257
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as PlDatasetSelector } from "./PlDatasetSelector.vue";
|
package/src/lib.ts
CHANGED
package/vitest.config.mts
CHANGED
|
@@ -3,8 +3,30 @@ import { defineConfig } from "vitest/config";
|
|
|
3
3
|
|
|
4
4
|
export default defineConfig(
|
|
5
5
|
createVitestVueConfig({
|
|
6
|
+
resolve: {
|
|
7
|
+
conditions: ["sources"],
|
|
8
|
+
},
|
|
6
9
|
test: {
|
|
7
10
|
includeSource: ["src/**/*.{js,ts}"],
|
|
11
|
+
setupFiles: ["./src/__tests__/setup.ts"],
|
|
12
|
+
projects: [
|
|
13
|
+
{
|
|
14
|
+
extends: true,
|
|
15
|
+
test: {
|
|
16
|
+
name: "node",
|
|
17
|
+
environment: "node",
|
|
18
|
+
include: ["src/**/*.test.ts"],
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
extends: true,
|
|
23
|
+
test: {
|
|
24
|
+
name: "jsdom",
|
|
25
|
+
environment: "jsdom",
|
|
26
|
+
include: ["src/**/*.jsdomtest.ts"],
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
],
|
|
8
30
|
},
|
|
9
31
|
}),
|
|
10
32
|
);
|