@webx-ui/module-catalog-properties 0.1.13 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/PropertiesPage-B1jxbWZh.js +370 -0
- package/dist/PropertiesPage-B1jxbWZh.js.map +1 -0
- package/dist/PropertyEditorPage-C0o03q-A.js +198 -0
- package/dist/PropertyEditorPage-C0o03q-A.js.map +1 -0
- package/dist/index-B2Yl11Yn.js +1875 -0
- package/dist/index-B2Yl11Yn.js.map +1 -0
- package/dist/index.d.ts +14 -2
- package/dist/index.js +22 -2415
- package/dist/index.js.map +1 -1
- package/dist/style.css +1 -1
- package/package.json +6 -6
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-B2Yl11Yn.js","sources":["../src/api.ts","../src/format.ts","../src/messages.ts","../src/i18n.ts","../src/CategoryPropertiesField.vue","../src/editor.ts","../src/IntervalsField.vue","../src/NumberExample.vue","../src/ValueSelect.vue","../src/ValueTreeSelect.vue","../src/ProductPropertiesField.vue","../src/TypeField.vue","../src/MergeDialog.vue","../src/ValueDialog.vue","../src/ValueRow.vue","../src/ValuesField.vue","../src/module.ts","../src/index.ts"],"sourcesContent":["import type { AdminContext } from '@webx-ui/module-admin'\nimport type { ScreenModel } from '@webx-ui/schema'\nimport type {\n CategorySet,\n EffectiveSet,\n PropertiesPage,\n PropertyDetail,\n PropertyInterval,\n PropertyQuery,\n PropertyValue,\n Words,\n} from './types'\n\n/** Where the properties answer under the panel's API — `CatalogPropertiesServiceProvider::SOURCE`. */\nexport const PROPERTIES_API = 'catalog/properties'\n\n/** Where their groups do: the panel's shared category API. */\nexport const GROUPS_API = 'catalog/property-groups'\n\n/** Where the set in force for a product form is — `catalog/property-sets/{category}`. */\nexport const SETS_API = 'catalog/property-sets'\n\n/** What a value is written with; a field left out is not touched. */\nexport interface ValueInput {\n title?: Words | string\n slug?: Words | string\n parent_id?: number | null\n color?: string | null\n image_id?: number | null\n}\n\nexport interface CatalogPropertiesApi {\n list(query?: PropertyQuery): Promise<PropertiesPage>\n get(id: number): Promise<PropertyDetail>\n /** The values of `catalog.property-form`; a refused field comes back as a 422 under its name. */\n create(values: ScreenModel): Promise<PropertyDetail>\n save(id: number, values: ScreenModel): Promise<PropertyDetail>\n reorder(ids: number[]): Promise<void>\n remove(id: number): Promise<void>\n restore(id: number): Promise<PropertyDetail>\n /** All the intervals at once, in order: one without an id is new, one left out is gone. */\n saveIntervals(id: number, intervals: PropertyInterval[]): Promise<PropertyInterval[]>\n\n /** The children of `parent` (null — the top) in the book's order. */\n values(id: number, parent?: number | null): Promise<PropertyValue[]>\n /** Whatever matches, at any depth — one page. */\n searchValues(id: number, q: string, perPage?: number): Promise<PropertyValue[]>\n /** These values, each with the path down to it. */\n valuesById(id: number, ids: number[]): Promise<PropertyValue[]>\n createValue(id: number, input: ValueInput): Promise<PropertyValue>\n saveValue(id: number, value: number, input: ValueInput): Promise<PropertyValue>\n /** Under `parent` (null — the top), before `before` (null — last). */\n moveValue(\n id: number,\n value: number,\n parent: number | null,\n before: number | null,\n ): Promise<PropertyValue>\n /** `A → B`: how many products moved, or would move with `dryRun`. */\n mergeValue(id: number, value: number, into: number, dryRun?: boolean): Promise<number>\n /** A 422 with `meta.products` while products hold it. */\n removeValue(id: number, value: number): Promise<void>\n\n categorySet(category: number): Promise<CategorySet>\n saveCategorySet(category: number, ids: number[]): Promise<CategorySet>\n effectiveSet(category: number): Promise<EffectiveSet>\n}\n\nexport function propertySearch(query: PropertyQuery): URLSearchParams {\n const search = new URLSearchParams()\n\n if (query.q) search.set('q', query.q)\n if (query.type) search.set('type', query.type)\n if (query.group != null) search.set('group', String(query.group))\n if (query.trashed) search.set('trashed', '1')\n for (const id of query.ids ?? []) search.append('ids[]', String(id))\n if (query.page && query.page > 1) search.set('page', String(query.page))\n if (query.per_page) search.set('per_page', String(query.per_page))\n\n return search\n}\n\nexport function createPropertiesApi(admin: AdminContext): CatalogPropertiesApi {\n const base = `${admin.apiPath}/${PROPERTIES_API}`\n const data = <T>(body: { data: T }): T => body.data\n const withQuery = (path: string, search: URLSearchParams) =>\n search.size > 0 ? `${path}?${search}` : path\n\n return {\n list: (query = {}) =>\n admin.http.get<PropertiesPage>(withQuery(base, propertySearch({ per_page: 500, ...query }))),\n get: (id) => admin.http.get<{ data: PropertyDetail }>(`${base}/${id}`).then(data),\n create: (values) => admin.http.post<{ data: PropertyDetail }>(base, { values }).then(data),\n save: (id, values) =>\n admin.http.put<{ data: PropertyDetail }>(`${base}/${id}`, { values }).then(data),\n reorder: (ids) => admin.http.post<void>(`${base}/reorder`, { ids }).then(() => undefined),\n remove: (id) => admin.http.delete<void>(`${base}/${id}`).then(() => undefined),\n restore: (id) =>\n admin.http.post<{ data: PropertyDetail }>(`${base}/${id}/restore`, {}).then(data),\n saveIntervals: (id, intervals) =>\n admin.http\n .put<{ data: PropertyInterval[] }>(`${base}/${id}/intervals`, {\n intervals: intervals.map(({ id: interval, title, slug, min, max }) => ({\n id: interval ?? null,\n title,\n slug,\n min,\n max,\n })),\n })\n .then(data),\n\n values: (id, parent = null) => {\n const search = new URLSearchParams()\n\n if (parent !== null) search.set('parent_id', String(parent))\n\n return admin.http\n .get<{ data: PropertyValue[] }>(withQuery(`${base}/${id}/values`, search))\n .then(data)\n },\n searchValues: (id, q, perPage = 50) =>\n admin.http\n .get<{\n data: PropertyValue[]\n }>(withQuery(`${base}/${id}/values`, new URLSearchParams({ q, per_page: String(perPage) })))\n .then(data),\n valuesById: (id, ids) => {\n if (ids.length === 0) return Promise.resolve([])\n\n const search = new URLSearchParams()\n\n for (const one of ids) search.append('ids[]', String(one))\n\n return admin.http\n .get<{ data: PropertyValue[] }>(withQuery(`${base}/${id}/values`, search))\n .then(data)\n },\n createValue: (id, input) =>\n admin.http.post<{ data: PropertyValue }>(`${base}/${id}/values`, input).then(data),\n saveValue: (id, value, input) =>\n admin.http.put<{ data: PropertyValue }>(`${base}/${id}/values/${value}`, input).then(data),\n moveValue: (id, value, parent, before) =>\n admin.http\n .post<{ data: PropertyValue }>(`${base}/${id}/values/${value}/move`, {\n parent_id: parent,\n before_id: before,\n })\n .then(data),\n mergeValue: (id, value, into, dryRun = false) =>\n admin.http\n .post<{ data: { moved: number } }>(`${base}/${id}/values/${value}/merge`, {\n into,\n dry_run: dryRun,\n })\n .then((body) => body.data.moved),\n removeValue: (id, value) =>\n admin.http.delete<void>(`${base}/${id}/values/${value}`).then(() => undefined),\n\n categorySet: (category) =>\n admin.http\n .get<{ data: CategorySet }>(`${admin.apiPath}/catalog/categories/${category}/properties`)\n .then(data),\n saveCategorySet: (category, ids) =>\n admin.http\n .put<{\n data: CategorySet\n }>(`${admin.apiPath}/catalog/categories/${category}/properties`, { ids })\n .then(data),\n effectiveSet: (category) =>\n admin.http.get<{ data: EffectiveSet }>(`${admin.apiPath}/${SETS_API}/${category}`).then(data),\n }\n}\n","import { localizedValue } from '@webx-ui/core'\nimport type { PropertyRow, Words } from './types'\n\n/**\n * A map of languages in one of them, the first written one where it is empty. The server sends an\n * empty map as `[]` — PHP's empty array — which reads as no words at all.\n */\nexport function wordsIn(words: Words | string | undefined, locale: string, fallback = ''): string {\n if (words === null || words === undefined || Array.isArray(words)) return fallback\n\n return localizedValue(words, locale, fallback)\n}\n\n/** What a property is called in the panel: its name, its code, its number — in that order. */\nexport function propertyName(property: Pick<PropertyRow, 'id' | 'title' | 'code'>, locale: string) {\n return wordsIn(property.title, locale) || wordsIn(property.code, locale) || `#${property.id}`\n}\n\nexport interface NumberShape {\n precision?: number | null\n prefix?: string | null\n suffix?: string | null\n}\n\n/**\n * A number as the site shows it (§3.1): the property's precision, the language's decimal mark,\n * the prefix and the suffix glued on as written — `M8`, `⌀12 мм`, `1,35 кг`. The same rule as\n * `Property::formatNumber()` on the server, so the example in the form is what the card will say.\n */\nexport function formatNumber(value: number, shape: NumberShape, locale: string): string {\n const digits = Math.max(0, Math.min(6, Math.trunc(shape.precision ?? 0)))\n let number: string\n\n try {\n number = new Intl.NumberFormat(locale || undefined, {\n minimumFractionDigits: digits,\n maximumFractionDigits: digits,\n }).format(value)\n } catch {\n number = value.toFixed(digits)\n }\n\n return `${shape.prefix ?? ''}${number}${shape.suffix ?? ''}`\n}\n\n/** The number a live example shows: twelve, with as many digits as the property keeps. */\nexport function exampleNumber(precision: number | null | undefined): number {\n const digits = Math.max(0, Math.min(6, Math.trunc(precision ?? 0)))\n\n return digits === 0 ? 12 : Number((12.5).toFixed(Math.min(digits, 1)))\n}\n\n/**\n * The decimals a field of a product keeps: the property's precision, or more when the product\n * holds more — a number is stored as it is, and a field that rounded `0.85` to `1` would save\n * the `1`.\n */\nexport function fieldDecimals(precision: number, held: number | null): number {\n const own = held === null ? 0 : (String(held).split('.')[1]?.length ?? 0)\n\n return Math.min(6, Math.max(precision, own))\n}\n","import type { Messages } from '@webx-ui/module-admin'\n\n/**\n * The English this package speaks on its own, before the server's dictionary arrives, or without\n * one. The server ships the same lines under `webx-catalog-properties::` and overrides these;\n * `messages.test.ts` keeps the two sets of keys equal. Only the groups the panel reads are here —\n * the refusals are the server's to say.\n */\nexport const catalogPropertiesMessages: Record<string, Messages> = {\n module: {\n title: 'Properties',\n property: 'Property',\n group: 'Property group',\n value: 'Property value',\n },\n property: {\n 'tab-main': 'Main',\n 'tab-values': 'Values',\n 'tab-intervals': 'Intervals',\n 'tab-history': 'History',\n 'card-values': 'Values',\n 'card-filter': 'Filter and search',\n 'card-showing': 'Where it is shown',\n title: 'Name',\n code: 'Code',\n 'code-help':\n 'Latin letters, digits and hyphens: the property in a filter address (color_black), per language. Made from the name when left empty.',\n type: 'Type',\n 'type-help': 'Chosen once: the values of the products have its shape.',\n types: {\n select: 'Reference book',\n number: 'Number',\n text: 'Text',\n bool: 'Yes / no',\n },\n group_id: 'Group',\n is_multiple: 'Several values',\n is_tree: 'Values in a tree',\n leaves_only: 'Only the last level',\n is_filterable: 'In the filter',\n filter_mode: 'Filter by',\n modes: {\n slider: 'Slider',\n intervals: 'Intervals',\n },\n is_indexable: 'Pages of one value open to search engines',\n is_searchable: 'Search by value',\n in_card: 'On the card in the catalogue',\n on_page: 'In the specifications of the product',\n in_list: 'Column in the list of products',\n value_order: 'Order of values',\n orders: {\n alpha: 'Alphabetical',\n manual: 'By hand',\n },\n has_color: 'Values have a colour',\n has_image: 'Values have a picture',\n unit_prefix: 'Before the number',\n unit_suffix: 'After the number',\n precision: 'Digits after the point',\n toggle_slug: 'The word for «yes» in an address',\n seo_pattern: 'Page title pattern',\n 'seo-pattern-help':\n \"{category}, {property} and {value} are replaced. Empty — the catalogue's own pattern.\",\n },\n value: {\n title: 'Name',\n slug: 'Slug',\n color: 'Colour',\n image: 'Picture',\n merged: 'Merged',\n 'merged-line': ':value, products: :count',\n },\n product: {\n tab: 'Specifications',\n properties: 'Properties',\n property: 'Property',\n value: 'Value',\n yes: 'Yes',\n },\n group: {\n title: 'Name',\n is_visible: 'Heading on the page',\n 'visible-help':\n 'Off, the properties of the group stand in the specifications without its heading.',\n new: 'New group',\n empty: 'No groups yet.',\n 'empty-help':\n 'A group is a heading of the specifications — «Screen», «Processor». A property without one stands last, without a heading.',\n order: 'The order here is the order of the headings in the specifications of a product',\n hidden: 'Heading not shown',\n count: 'Properties: :count',\n 'delete-blocked':\n 'While properties are in this group it cannot go — move them to another first.',\n 'delete-text': 'It goes to the bin.',\n deleted: 'The group is in the bin.',\n saved: 'The group is saved.',\n },\n panel: {\n 'category-tab': 'Properties',\n new: 'New property',\n groups: 'Groups',\n 'groups-title': 'Groups of properties',\n 'view-all': 'Properties',\n 'view-deleted': 'Deleted',\n 'type-any': 'Any type',\n 'group-any': 'Any group',\n empty: 'No properties yet.',\n 'empty-help':\n 'A property is what a product is described by — a colour, a weight, Wi-Fi — and, when it is in the filter, what the catalogue is narrowed by.',\n 'empty-found': 'Nothing here.',\n order:\n \"The order here is the order of the filter's blocks, unless a category sets its own on its «Filters» tab.\",\n 'order-narrowed': 'The order is dragged on the whole list: clear the type and the group first.',\n count: 'Products: :count',\n edit: 'Edit',\n delete: 'Delete',\n restore: 'Restore',\n cancel: 'Cancel',\n create: 'Create',\n save: 'Save',\n add: 'Add',\n search: 'Search',\n searching: 'Searching…',\n 'nothing-found': 'Nothing found',\n 'delete-title': 'Delete «:name»?',\n 'delete-text':\n 'It goes to «Deleted»: its filter and its old addresses go, the values of the products stay, and a restore brings everything back.',\n deleted: 'The property is in «Deleted».',\n restored: 'The property is back.',\n 'in-bin': 'Deleted',\n 'reorder-failed': 'The order was not saved.',\n saved: 'The property is saved.',\n 'save-failed': 'Not saved: check the marked fields.',\n untitled: 'Untitled',\n trail: 'Where you are',\n 'leave-title': 'Leave without saving?',\n 'leave-text': 'The changes to «Main» are not saved yet.',\n leave: 'Leave',\n example: 'On the site:',\n 'slug-help':\n \"The value in a filter's address: /laptops/color_black/. Made from the name when left empty.\",\n 'values-unsaved': 'The values are written once the property is saved as a reference book.',\n 'values-failed': 'The values did not load. Reload the page.',\n 'values-empty': 'No values yet.',\n 'values-order-manual':\n 'By hand: the order and the nesting are dragged, and the site shows them so.',\n 'values-order-alpha':\n 'Alphabetical: the site sorts them by name in each language. Switch the order to «By hand» on «Main» to drag them.',\n 'value-new': 'New value — its name, then Enter',\n 'value-new-inside': 'New value in «:name»',\n 'value-add-inside': 'Add inside',\n 'value-delete-title': 'Delete «:name»?',\n 'value-delete-text': 'No product holds it. Its old address leads to the category without it.',\n 'value-delete-branch':\n 'No product holds it, nor anything under it. Everything under it goes too.',\n 'value-in-use': 'Products hold this value: merge it into another instead. Products: :count',\n 'picture-pick': 'Choose a picture',\n 'picture-change': 'Another picture',\n 'picture-remove': 'Remove',\n 'value-pick': 'Choose',\n 'value-create': 'Create «:name»',\n 'merge-with': 'Merge with…',\n 'merge-title': 'Merge «:name»',\n 'merge-into': 'Into',\n 'merge-help':\n 'Its products get the value chosen here, its addresses lead there, and it is gone.',\n 'merge-confirm': '«:name» becomes «:target» on the products. Products: :count',\n merge: 'Merge',\n merged: 'Merged. Products moved: :count',\n 'intervals-unsaved':\n 'Intervals are the filter of a number by steps: save the property with «Filter by: Intervals» first.',\n 'intervals-help':\n 'A step includes its lower end and not its upper one: «1–2 kg» and «2–3 kg» do not share a product of exactly 2 kg. An empty end is open.',\n 'intervals-empty': 'No intervals yet.',\n 'interval-title': 'Label',\n 'interval-min': 'From',\n 'interval-max': 'Up to',\n 'interval-slug': 'Slug',\n 'interval-open': 'Open',\n 'interval-add': 'Add an interval',\n 'intervals-sort': 'Sort by bounds',\n 'intervals-save': 'Save the intervals',\n 'intervals-saved': 'The intervals are saved.',\n 'set-unsaved': 'The set is chosen once the category is saved.',\n 'set-failed': 'The properties did not load. Reload the page.',\n 'set-help':\n 'The products of the category and of everything under it are described by these properties. The ones from above come with the category and are removed where they were added.',\n 'set-from': 'from «:name»',\n 'set-empty': 'The category adds no properties of its own.',\n 'set-add': 'Add a property…',\n 'set-remove': 'Remove «:name» from the set',\n 'product-no-category':\n 'The properties of a product are those of its main category: choose one on «Main».',\n 'product-empty-set':\n \"The main category has no properties. They are chosen on the category's «Properties» tab.\",\n outside: \"Outside the category's set: :count\",\n 'outside-help':\n 'The product holds these, but its main category does not have them: they are not shown anywhere. Moved back to such a category, the product shows them again.',\n 'outside-clear': 'Delete these values',\n 'outside-clear-title': 'Delete the values outside the set?',\n 'outside-clear-text':\n 'They are deleted from the product for good; the journal keeps what they were.',\n 'outside-cleared': 'The values outside the set are deleted.',\n },\n}\n","import { useAdmin } from '@webx-ui/module-admin'\nimport { catalogPropertiesMessages } from './messages'\n\n/** The server's dictionary for this package: `webx-catalog-properties::`. */\nexport const NAMESPACE = 'webx-catalog-properties'\n\nconst seeded = new WeakSet<object>()\n\n/** Puts this package's English under the panel's dictionary, once per panel. */\nexport function useCatalogPropertiesMessages(): void {\n try {\n const { i18n } = useAdmin()\n\n if (!seeded.has(i18n)) {\n i18n.defaults(NAMESPACE, catalogPropertiesMessages)\n seeded.add(i18n)\n }\n } catch {\n // Outside a panel there is no dictionary to seed, and `useTranslate` falls back on its own.\n }\n}\n","<script setup lang=\"ts\">\nimport { computed, ref, watch } from 'vue'\nimport {\n toast,\n WxAlert,\n WxButton,\n WxSelect,\n WxSkeleton,\n WxSortableList,\n WxText,\n type SelectModelValue,\n type SelectOption,\n} from '@webx-ui/core'\nimport { useAdmin, useErrorText, useTranslate } from '@webx-ui/module-admin'\nimport { useCatalogCategoryEditor } from '@webx-ui/module-catalog'\nimport { createPropertiesApi } from './api'\nimport { propertyName } from './format'\nimport { NAMESPACE, useCatalogPropertiesMessages } from './i18n'\nimport type { CategorySet, PropertyRow } from './types'\n\n/**\n * `wx-catalog-category-properties`: the «Properties» tab of a category (§7.2) — its set.\n *\n * The set is inherited (decision 5): at the top, muted, what the categories above give it, each\n * with where it comes from; below, what it adds itself — found by search, dragged into order,\n * taken away. An inherited one cannot be taken away here, and cannot be added again: it is taken\n * away where it was added.\n *\n * Saved at once, each change a request, like the gallery of a product: the set is a record of its\n * own, the products of the whole branch are marked for the index when it changes, and the\n * category's own button is about its fields.\n */\ndefineOptions({ name: 'WxCatalogCategoryProperties' })\n\nconst admin = useAdmin()\nconst api = createPropertiesApi(admin)\nconst editor = useCatalogCategoryEditor()\nuseCatalogPropertiesMessages()\n\nconst t = useTranslate(NAMESPACE)\nconst message = useErrorText()\n\nconst locale = computed(() => admin.i18n.state.locale)\nconst category = computed(() => editor?.category.value?.id ?? null)\nconst locked = computed(() => (editor?.locked.value ?? true) || !admin.can('catalog.manage'))\n\nconst set = ref<CategorySet | null>(null)\nconst own = ref<PropertyRow[]>([])\nconst all = ref<PropertyRow[]>([])\nconst loading = ref(true)\nconst failed = ref(false)\nconst saving = ref(false)\nconst picked = ref<number | null>(null)\n\nconst taken = computed(\n () =>\n new Set([\n ...(set.value?.inherited ?? []).map((row) => row.property.id),\n ...own.value.map((row) => row.id),\n ]),\n)\n\nconst offered = computed<SelectOption[]>(() =>\n all.value\n .filter((property) => !taken.value.has(property.id))\n .map((property) => ({ value: property.id, label: propertyName(property, locale.value) })),\n)\n\nfunction take(answer: CategorySet): void {\n set.value = answer\n own.value = [...answer.own]\n}\n\nasync function load(): Promise<void> {\n if (category.value === null) return\n\n loading.value = true\n failed.value = false\n\n try {\n const [answer, page] = await Promise.all([api.categorySet(category.value), api.list()])\n\n take(answer)\n all.value = page.data\n } catch {\n failed.value = true\n } finally {\n loading.value = false\n }\n}\n\nwatch(category, () => void load(), { immediate: true })\n\n/* A category moved under another inherits another branch's set; the editor hands the move over. */\nwatch(\n () => editor?.category.value?.parent_id,\n (now, before) => {\n if (before !== undefined && now !== before) void load()\n },\n)\n\nasync function save(ids: number[]): Promise<void> {\n if (category.value === null) return\n\n saving.value = true\n\n try {\n take(await api.saveCategorySet(category.value, ids))\n } catch (error) {\n const body = (error as { body?: { errors?: Record<string, string[]> } }).body\n const first = body?.errors ? Object.values(body.errors)[0]?.[0] : undefined\n\n toast.danger(first ?? message(error))\n // Back to what the server has: the screen must not disagree with the set.\n if (set.value) own.value = [...set.value.own]\n } finally {\n saving.value = false\n }\n}\n\nfunction add(value: SelectModelValue): void {\n if (typeof value !== 'number') return\n\n picked.value = null\n void save([...own.value.map((row) => row.id), value])\n}\n\nfunction remove(id: number): void {\n void save(own.value.filter((row) => row.id !== id).map((row) => row.id))\n}\n\nfunction reorder(): void {\n void save(own.value.map((row) => row.id))\n}\n\nconst typeOf = (row: PropertyRow) => t(`property.types.${row.type}`)\n</script>\n\n<template>\n <div class=\"wx-catalog-category-properties\">\n <wx-alert\n v-if=\"category === null\"\n type=\"info\"\n variant=\"soft\"\n :description=\"t('panel.set-unsaved')\"\n />\n\n <wx-skeleton v-else-if=\"loading\" :rows=\"4\" />\n\n <wx-alert\n v-else-if=\"failed\"\n type=\"warning\"\n variant=\"soft\"\n :description=\"t('panel.set-failed')\"\n />\n\n <template v-else>\n <wx-text size=\"sm\" tone=\"muted\">{{ t('panel.set-help') }}</wx-text>\n\n <ul v-if=\"set && set.inherited.length > 0\" class=\"wx-catalog-category-properties__inherited\">\n <li\n v-for=\"row in set.inherited\"\n :key=\"row.property.id\"\n class=\"wx-catalog-category-properties__row is-inherited\"\n >\n <span class=\"wx-catalog-category-properties__name\">\n {{ propertyName(row.property, locale) }}\n </span>\n <wx-text size=\"sm\" tone=\"muted\" truncate>\n {{ typeOf(row.property) }} · {{ t('panel.set-from', { name: row.from.name }) }}\n </wx-text>\n </li>\n </ul>\n\n <wx-sortable-list\n v-model=\"own\"\n size=\"sm\"\n item-key=\"id\"\n :item-label=\"(row: PropertyRow) => propertyName(row, locale)\"\n :disabled=\"locked || saving\"\n :empty-text=\"t('panel.set-empty')\"\n @move=\"reorder\"\n >\n <template #default=\"{ item }\">\n <span class=\"wx-catalog-category-properties__row\">\n <span class=\"wx-catalog-category-properties__name\">\n {{ propertyName(item as PropertyRow, locale) }}\n </span>\n <wx-text size=\"sm\" tone=\"muted\" truncate>{{ typeOf(item as PropertyRow) }}</wx-text>\n </span>\n </template>\n\n <template #actions=\"{ item }\">\n <wx-button\n v-if=\"!locked\"\n size=\"sm\"\n variant=\"text\"\n icon=\"close\"\n :disabled=\"saving\"\n :aria-label=\"t('panel.set-remove', { name: propertyName(item as PropertyRow, locale) })\"\n @click=\"remove((item as PropertyRow).id)\"\n />\n </template>\n </wx-sortable-list>\n\n <wx-select\n v-if=\"!locked\"\n class=\"wx-catalog-category-properties__add\"\n :model-value=\"picked\"\n :options=\"offered\"\n :placeholder=\"t('panel.set-add')\"\n :empty-text=\"t('panel.nothing-found')\"\n :disabled=\"saving\"\n filterable\n @update:model-value=\"add\"\n />\n </template>\n </div>\n</template>\n\n<style scoped>\n.wx-catalog-category-properties {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-12);\n}\n\n.wx-catalog-category-properties__inherited {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-4);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.wx-catalog-category-properties__row {\n display: flex;\n align-items: baseline;\n gap: var(--wx-space-8);\n min-width: 0;\n}\n\n/* Inherited rows start where the own rows' names do — past the list's frame and its grips — so\n the set reads as one column of names. */\n.wx-catalog-category-properties__row.is-inherited {\n padding-inline-start: var(--wx-space-48);\n color: var(--wx-text-muted);\n}\n\n.wx-catalog-category-properties__name {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.wx-catalog-category-properties__add {\n max-width: var(--wx-field-max-width, 480px);\n}\n</style>\n","import { inject, provide, type InjectionKey, type Ref } from 'vue'\nimport type { ScreenModel } from '@webx-ui/schema'\nimport type { PropertyInterval, PropertyRow } from './types'\n\n/**\n * What the property's editor knows and the nodes of `catalog.property-form` do not: which property\n * it is — the values and the intervals are records of their own, saved by requests of their own —\n * and what the form says right now, which the type field and the live example read.\n */\nexport interface PropertyEditorContext {\n /** The property as the server last answered it, or `null` while the first request is out. */\n property: Ref<PropertyRow | null>\n /** The values of the screen as they are right now, edits included. */\n values: Ref<ScreenModel>\n /** The intervals as the server last answered them; the node keeps its own edits. */\n intervals: Ref<PropertyInterval[]>\n /** Closed for writing: no permission, or a save in flight. */\n locked: Ref<boolean>\n}\n\nexport const propertyEditorKey: InjectionKey<PropertyEditorContext> = Symbol('wx-catalog-property')\n\nexport function providePropertyEditor(editor: PropertyEditorContext): void {\n provide(propertyEditorKey, editor)\n}\n\n/** The editor above this node, or `null` outside one — a demo, a test, a stray screen. */\nexport function usePropertyEditor(): PropertyEditorContext | null {\n return inject(propertyEditorKey, null)\n}\n","<script setup lang=\"ts\">\nimport { computed, ref, watch } from 'vue'\nimport {\n toast,\n WxAction,\n WxAlert,\n WxButton,\n WxInput,\n WxInputNumber,\n WxSortableList,\n WxText,\n type LocalizedValue,\n} from '@webx-ui/core'\nimport { useAdmin, useErrorText, useTranslate } from '@webx-ui/module-admin'\nimport { createPropertiesApi } from './api'\nimport { usePropertyEditor } from './editor'\nimport { NAMESPACE, useCatalogPropertiesMessages } from './i18n'\nimport type { PropertyInterval } from './types'\n\n/**\n * `wx-catalog-property-intervals`: the steps a number is filtered by (§7.1, «Intervals») — a\n * label, where it starts, where it stops, and its slug in the address, per language.\n *\n * An interval is `[from, to)`: «1–2 kg» and «2–3 kg» do not share a product of exactly 2. Either\n * end may be empty — «up to 1 kg», «from 3 kg». They may overlap («up to 1 kg», «up to 2 kg»);\n * that is the admin's choice, and each counts honestly.\n *\n * The table is saved as a whole with a button of its own, because its rows are records the\n * property's save does not carry, and a half-typed row should not be written a keystroke at a\n * time. «Sort by bounds» puts them in the order a visitor reads them.\n */\ndefineOptions({ name: 'WxCatalogPropertyIntervals' })\n\ninterface Row {\n key: string\n id: number | null\n title: LocalizedValue\n slug: LocalizedValue\n min: number | null\n max: number | null\n}\n\nconst admin = useAdmin()\nconst api = createPropertiesApi(admin)\nconst editor = usePropertyEditor()\nuseCatalogPropertiesMessages()\n\nconst t = useTranslate(NAMESPACE)\nconst message = useErrorText()\n\nconst property = computed(() => editor?.property.value ?? null)\nconst locked = computed(() => editor?.locked.value ?? true)\n\nconst rows = ref<Row[]>([])\nconst snapshot = ref('')\nconst saving = ref(false)\nconst errors = ref<Record<string, string[]>>({})\n\nlet made = 0\n\nconst words = (map: PropertyInterval['title']): LocalizedValue =>\n map && !Array.isArray(map) ? { ...map } : {}\n\nfunction rowOf(interval: PropertyInterval): Row {\n return {\n key: interval.id ? `i${interval.id}` : `n${++made}`,\n id: interval.id ?? null,\n title: words(interval.title),\n slug: words(interval.slug),\n min: interval.min,\n max: interval.max,\n }\n}\n\nconst shape = (list: Row[]) =>\n JSON.stringify(list.map(({ id, title, slug, min, max }) => ({ id, title, slug, min, max })))\n\nfunction take(intervals: PropertyInterval[]): void {\n rows.value = intervals.map(rowOf)\n snapshot.value = shape(rows.value)\n}\n\nwatch(\n () => editor?.intervals.value,\n (intervals) => take(intervals ?? []),\n { immediate: true },\n)\n\nconst dirty = computed(() => shape(rows.value) !== snapshot.value)\n\nfunction add(): void {\n const last = rows.value[rows.value.length - 1]\n\n // The next step starts where the last one stops — the usual way a scale is written.\n rows.value = [\n ...rows.value,\n { key: `n${++made}`, id: null, title: {}, slug: {}, min: last?.max ?? null, max: null },\n ]\n}\n\nfunction remove(key: string): void {\n rows.value = rows.value.filter((row) => row.key !== key)\n}\n\n/** Open lower ends first, then by where each starts, then by where it stops, open last. */\nfunction sortByBounds(): void {\n const low = (row: Row) => row.min ?? Number.NEGATIVE_INFINITY\n const high = (row: Row) => row.max ?? Number.POSITIVE_INFINITY\n\n rows.value = [...rows.value].sort((a, b) => low(a) - low(b) || high(a) - high(b))\n}\n\nfunction errorOf(index: number, field: string): string | undefined {\n const prefix = `intervals.${index}.${field}`\n const key = Object.keys(errors.value).find(\n (one) => one === prefix || one.startsWith(`${prefix}.`),\n )\n\n return key === undefined ? undefined : errors.value[key]?.[0]\n}\n\nasync function save(): Promise<void> {\n if (!property.value || saving.value) return\n\n saving.value = true\n errors.value = {}\n\n try {\n const saved = await api.saveIntervals(\n property.value.id,\n rows.value.map(({ id, title, slug, min, max }) => ({ id, title, slug, min, max })),\n )\n\n if (editor) editor.intervals.value = saved\n else take(saved)\n toast.success(t('panel.intervals-saved'))\n } catch (error) {\n const body = (error as { body?: { errors?: Record<string, string[]> } }).body\n\n if (body?.errors) {\n errors.value = body.errors\n toast.danger(t('panel.save-failed'))\n } else {\n toast.danger(message(error))\n }\n } finally {\n saving.value = false\n }\n}\n</script>\n\n<template>\n <div class=\"wx-catalog-intervals\">\n <wx-alert\n v-if=\"!property || property.filter_mode !== 'intervals'\"\n type=\"info\"\n variant=\"soft\"\n :description=\"t('panel.intervals-unsaved')\"\n />\n\n <template v-else>\n <wx-text size=\"sm\" tone=\"muted\">{{ t('panel.intervals-help') }}</wx-text>\n\n <div class=\"wx-catalog-intervals__head\" aria-hidden=\"true\">\n <span>{{ t('panel.interval-title') }}</span>\n <span>{{ t('panel.interval-min') }}</span>\n <span>{{ t('panel.interval-max') }}</span>\n <span>{{ t('panel.interval-slug') }}</span>\n </div>\n\n <wx-sortable-list\n v-model=\"rows\"\n class=\"wx-catalog-intervals__list\"\n item-key=\"key\"\n :item-label=\"(row: Row) => row.title[admin.i18n.state.locale] ?? ''\"\n :disabled=\"locked\"\n :empty-text=\"t('panel.intervals-empty')\"\n >\n <template #default=\"{ item, index }\">\n <div class=\"wx-catalog-intervals__row\">\n <wx-input\n v-model=\"(item as Row).title\"\n localized\n size=\"sm\"\n :disabled=\"locked\"\n :aria-label=\"t('panel.interval-title')\"\n :status=\"errorOf(index, 'title') ? 'error' : undefined\"\n />\n <wx-input-number\n v-model=\"(item as Row).min\"\n size=\"sm\"\n :controls=\"false\"\n :disabled=\"locked\"\n :placeholder=\"t('panel.interval-open')\"\n :aria-label=\"t('panel.interval-min')\"\n />\n <wx-input-number\n v-model=\"(item as Row).max\"\n size=\"sm\"\n :controls=\"false\"\n :disabled=\"locked\"\n :placeholder=\"t('panel.interval-open')\"\n :aria-label=\"t('panel.interval-max')\"\n :status=\"errorOf(index, 'max') ? 'error' : undefined\"\n />\n <wx-input\n v-model=\"(item as Row).slug\"\n localized\n size=\"sm\"\n :disabled=\"locked\"\n :aria-label=\"t('panel.interval-slug')\"\n :status=\"errorOf(index, 'slug') ? 'error' : undefined\"\n />\n <wx-text\n v-for=\"line in ['title', 'max', 'slug']\n .map((field) => errorOf(index, field))\n .filter(Boolean)\"\n :key=\"line\"\n class=\"wx-catalog-intervals__error\"\n size=\"sm\"\n >\n {{ line }}\n </wx-text>\n </div>\n </template>\n\n <template #actions=\"{ item }\">\n <wx-action\n type=\"remove\"\n :label=\"t('panel.delete')\"\n :disabled=\"locked\"\n @click=\"remove((item as Row).key)\"\n />\n </template>\n </wx-sortable-list>\n\n <div v-if=\"!locked\" class=\"wx-catalog-intervals__bar\">\n <wx-button size=\"sm\" icon=\"plus\" @click=\"add\">{{ t('panel.interval-add') }}</wx-button>\n <wx-button size=\"sm\" variant=\"outline\" :disabled=\"rows.length < 2\" @click=\"sortByBounds\">\n {{ t('panel.intervals-sort') }}\n </wx-button>\n <span class=\"wx-catalog-intervals__spacer\" />\n <wx-button type=\"primary\" size=\"sm\" :loading=\"saving\" :disabled=\"!dirty\" @click=\"save\">\n {{ t('panel.intervals-save') }}\n </wx-button>\n </div>\n </template>\n </div>\n</template>\n\n<style scoped>\n.wx-catalog-intervals {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-12);\n container-type: inline-size;\n}\n\n/* One grid for the head and every row, so the columns line up under their names. */\n.wx-catalog-intervals__head,\n.wx-catalog-intervals__row {\n display: grid;\n grid-template-columns: minmax(0, 2fr) minmax(0, 1fr) minmax(0, 1fr) minmax(0, 2fr);\n gap: var(--wx-space-8);\n align-items: center;\n}\n\n.wx-catalog-intervals__head {\n /* Over the rows' grid, which starts after the list's frame and the grip and stops before the\n delete button: measured against a row, so the names stand over their fields. */\n padding-inline: calc(var(--wx-space-48) + var(--wx-space-4))\n calc(var(--wx-space-64) + var(--wx-space-2));\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-sm);\n}\n\n.wx-catalog-intervals__row {\n flex: 1 1 auto;\n min-width: 0;\n}\n\n.wx-catalog-intervals__error {\n grid-column: 1 / -1;\n color: var(--wx-color-danger);\n}\n\n.wx-catalog-intervals__bar {\n display: flex;\n flex-wrap: wrap;\n gap: var(--wx-space-8);\n}\n\n.wx-catalog-intervals__spacer {\n flex: 1 1 auto;\n}\n\n/* A phone has no room for four fields in a line: two by two, and the head goes. */\n@container (max-width: 560px) {\n .wx-catalog-intervals__head {\n display: none;\n }\n\n .wx-catalog-intervals__row {\n grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);\n }\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { useLocales, WxText } from '@webx-ui/core'\nimport { useTranslate } from '@webx-ui/module-admin'\nimport { usePropertyEditor } from './editor'\nimport { exampleNumber, formatNumber, wordsIn } from './format'\nimport { NAMESPACE } from './i18n'\nimport type { Words } from './types'\n\n/**\n * `wx-catalog-property-example`: a number as the site will print it, while its prefix, suffix and\n * precision are typed — `⌀12 мм`, `M8`, `1,5 кг`. In the language being edited, because the units\n * are per language and so is the decimal mark; a space belongs to the suffix, which is why it is\n * shown and not guessed.\n */\ndefineOptions({ name: 'WxCatalogPropertyExample' })\n\nconst editor = usePropertyEditor()\nconst locales = useLocales()\nconst t = useTranslate(NAMESPACE)\n\nconst example = computed(() => {\n const values = editor?.values.value ?? {}\n const locale = locales.active.value\n const precision = Number(values.precision ?? 0)\n\n return formatNumber(\n exampleNumber(precision),\n {\n precision,\n prefix: wordsIn(values.unit_prefix as Words, locale),\n suffix: wordsIn(values.unit_suffix as Words, locale),\n },\n locale,\n )\n})\n</script>\n\n<template>\n <wx-text class=\"wx-catalog-property-example\" size=\"sm\" tone=\"muted\">\n {{ t('panel.example') }}\n <span class=\"wx-catalog-property-example__value\">{{ example }}</span>\n </wx-text>\n</template>\n\n<style scoped>\n.wx-catalog-property-example__value {\n color: var(--wx-text-strong);\n font-weight: var(--wx-font-weight-medium);\n /* The spaces are the admin's — a suffix « мм» keeps its own — so they are shown as typed. */\n white-space: pre;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, ref, watch } from 'vue'\nimport { toast, WxSelect, type SelectModelValue, type SelectOption } from '@webx-ui/core'\nimport { useAdmin, useErrorText, useTranslate } from '@webx-ui/module-admin'\nimport { createPropertiesApi } from './api'\nimport { wordsIn } from './format'\nimport { NAMESPACE } from './i18n'\nimport type { PropertyRow, PropertyValue } from './types'\n\n/**\n * A value of a flat reference book in the product form (§7.2): a combobox that searches the book\n * on the server — a book of three hundred colours is not an option list sent with the form — and\n * offers «Create \"…\"» for what it does not find, to whoever may write the catalogue.\n *\n * The chosen values are named by their own request, once: the form holds ids, and a combobox\n * showing «37» where «Black» belongs is the one thing this must not do.\n */\ndefineOptions({ name: 'WxCatalogPropertyValueSelect' })\n\nconst props = withDefaults(\n defineProps<{ property: PropertyRow; disabled?: boolean; ariaLabel?: string }>(),\n { disabled: false, ariaLabel: undefined },\n)\n\nconst value = defineModel<number | number[] | null>({ default: null })\n\nconst admin = useAdmin()\nconst api = createPropertiesApi(admin)\nconst t = useTranslate(NAMESPACE)\nconst message = useErrorText()\n\n/** The one option that is not a value: «Create \"…\"». Values are positive ids. */\nconst CREATE = -1\n\nconst locale = computed(() => admin.i18n.state.locale)\nconst canCreate = computed(() => admin.can('catalog.manage'))\n\nconst known = ref(new Map<number, string>())\nconst found = ref<number[]>([])\nconst term = ref('')\nconst creating = ref(false)\n\nconst chosen = computed<number[]>(() =>\n value.value === null ? [] : Array.isArray(value.value) ? value.value : [value.value],\n)\n\nfunction remember(values: PropertyValue[]): number[] {\n const next = new Map(known.value)\n\n for (const one of values) next.set(one.id, wordsIn(one.title, locale.value, `#${one.id}`))\n known.value = next\n\n return values.map((one) => one.id)\n}\n\nconst exact = computed(() => {\n const typed = term.value.trim().toLocaleLowerCase(locale.value)\n\n return [...known.value.values()].some((label) => label.toLocaleLowerCase(locale.value) === typed)\n})\n\nconst options = computed<SelectOption[]>(() => {\n const ids = [...new Set([...chosen.value, ...found.value])]\n const list: SelectOption[] = ids.map((id) => ({\n value: id,\n label: known.value.get(id) ?? `#${id}`,\n }))\n\n if (canCreate.value && term.value.trim() !== '' && !exact.value) {\n list.push({ value: CREATE, label: t('panel.value-create', { name: term.value.trim() }) })\n }\n\n return list\n})\n\n/* The chosen ones by name — asked only for ids the combobox cannot name yet. */\nwatch(\n chosen,\n async (ids) => {\n const missing = ids.filter((id) => !known.value.has(id))\n\n if (missing.length === 0) return\n\n try {\n remember(await api.valuesById(props.property.id, missing))\n } catch {\n // The ids stay and show as they are; the value is not lost for want of its name.\n }\n },\n { immediate: true },\n)\n\nlet timer: ReturnType<typeof setTimeout> | undefined\nlet asked = 0\n\nasync function search(text: string): Promise<void> {\n const ticket = ++asked\n\n try {\n const answer = await api.searchValues(props.property.id, text.trim(), 30)\n\n if (ticket === asked) found.value = remember(answer)\n } catch {\n if (ticket === asked) found.value = []\n }\n}\n\nfunction typed(text: string): void {\n term.value = text\n clearTimeout(timer)\n timer = setTimeout(() => void search(text), 200)\n}\n\nonBeforeUnmount(() => clearTimeout(timer))\n\nasync function create(): Promise<number | null> {\n const name = term.value.trim()\n\n if (name === '' || creating.value) return null\n\n creating.value = true\n\n try {\n const [id] = remember([\n await api.createValue(props.property.id, { title: { [locale.value]: name } }),\n ])\n\n term.value = ''\n\n return id ?? null\n } catch (error) {\n toast.danger(message(error))\n\n return null\n } finally {\n creating.value = false\n }\n}\n\nasync function pick(next: SelectModelValue): Promise<void> {\n const list = next === null ? [] : Array.isArray(next) ? next.map(Number) : [Number(next)]\n\n if (list.includes(CREATE)) {\n const made = await create()\n const rest = list.filter((id) => id !== CREATE)\n\n if (made !== null) rest.push(made)\n\n value.value = props.property.is_multiple ? rest : (made ?? chosen.value[0] ?? null)\n\n return\n }\n\n value.value = props.property.is_multiple ? list : (list[0] ?? null)\n}\n</script>\n\n<template>\n <wx-select\n :model-value=\"props.property.is_multiple ? chosen : (chosen[0] ?? null)\"\n :options=\"options\"\n :multiple=\"props.property.is_multiple\"\n :disabled=\"props.disabled || creating\"\n :aria-label=\"props.ariaLabel\"\n :placeholder=\"t('panel.value-pick')\"\n :empty-text=\"t('panel.nothing-found')\"\n filterable\n clearable\n @update:model-value=\"pick\"\n @search=\"typed\"\n @open=\"search(term)\"\n />\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref, watch } from 'vue'\nimport { WxTreeSelect, type TreeSelectValue } from '@webx-ui/core'\nimport { useAdmin, useTranslate } from '@webx-ui/module-admin'\nimport { createPropertiesApi } from './api'\nimport { wordsIn } from './format'\nimport { NAMESPACE } from './i18n'\nimport type { PropertyRow, PropertyValue, ValueNode } from './types'\n\n/**\n * A value of a tree-shaped reference book in the product form (§7.2): picked in the tree, which\n * reads a branch when it is opened. With «only the last level» a branch is opened but not chosen;\n * without it a node in the middle is a value too — «fits every BMW 3».\n *\n * A chosen value deep in an unopened tree is named by its path, which the server gives with it.\n */\ndefineOptions({ name: 'WxCatalogPropertyValueTree' })\n\nconst props = withDefaults(\n defineProps<{ property: PropertyRow; disabled?: boolean; ariaLabel?: string }>(),\n { disabled: false, ariaLabel: undefined },\n)\n\nconst value = defineModel<number | number[] | null>({ default: null })\n\nconst admin = useAdmin()\nconst api = createPropertiesApi(admin)\nconst t = useTranslate(NAMESPACE)\n\nconst locale = computed(() => admin.i18n.state.locale)\n\nconst roots = ref<ValueNode[]>([])\nconst paths = ref<ValueNode[][]>([])\n\nfunction nodeOf(one: PropertyValue): ValueNode {\n return {\n ...one,\n label: wordsIn(one.title, locale.value, `#${one.id}`),\n leaf: !one.has_children,\n blocked: props.property.leaves_only && one.has_children,\n children: undefined,\n }\n}\n\nconst chosen = computed<number[]>(() =>\n value.value === null ? [] : Array.isArray(value.value) ? value.value : [value.value],\n)\n\nasync function loadRoots(): Promise<void> {\n try {\n roots.value = (await api.values(props.property.id)).map(nodeOf)\n } catch {\n roots.value = []\n }\n}\n\nvoid loadRoots()\n\nwatch(\n chosen,\n async (ids) => {\n const named = new Set(paths.value.map((path) => path[path.length - 1]?.id))\n const missing = ids.filter((id) => !named.has(id))\n\n if (missing.length === 0) return\n\n try {\n const answer = await api.valuesById(props.property.id, missing)\n\n paths.value = [\n ...paths.value.filter((path) => ids.includes(path[path.length - 1]?.id ?? -1)),\n ...answer.map((one) => [...(one.ancestors ?? []).map(nodeOf), nodeOf(one)]),\n ]\n } catch {\n // Named by id until the tree is opened; the value itself is kept.\n }\n },\n { immediate: true },\n)\n\nconst selectedPath = computed(() =>\n props.property.is_multiple\n ? paths.value\n : (paths.value.find((path) => path[path.length - 1]?.id === chosen.value[0]) ?? []),\n)\n\nasync function load(node: ValueNode): Promise<ValueNode[]> {\n return (await api.values(props.property.id, node.id)).map(nodeOf)\n}\n\nfunction pick(next: TreeSelectValue): void {\n const list = next === null ? [] : Array.isArray(next) ? next.map(Number) : [Number(next)]\n\n value.value = props.property.is_multiple ? list : (list[0] ?? null)\n}\n</script>\n\n<template>\n <wx-tree-select\n :model-value=\"props.property.is_multiple ? chosen : (chosen[0] ?? null)\"\n :nodes=\"roots\"\n :multiple=\"props.property.is_multiple\"\n :check-strictly=\"true\"\n :selected-path=\"selectedPath\"\n :load=\"load\"\n lazy\n node-key=\"id\"\n label-key=\"label\"\n leaf-key=\"leaf\"\n disabled-key=\"blocked\"\n show-path\n clearable\n :disabled=\"props.disabled\"\n :aria-label=\"props.ariaLabel\"\n :placeholder=\"t('panel.value-pick')\"\n :empty-text=\"t('panel.values-empty')\"\n @update:model-value=\"pick\"\n />\n</template>\n","<script setup lang=\"ts\">\nimport { computed, inject, ref, watch } from 'vue'\nimport {\n confirm,\n toast,\n useLocales,\n WxAlert,\n WxButton,\n WxFormItem,\n WxInput,\n WxInputNumber,\n WxSkeleton,\n WxSwitch,\n WxText,\n type LocalizedValue,\n} from '@webx-ui/core'\nimport { useAdmin, useErrorText, useTranslate } from '@webx-ui/module-admin'\nimport { createCatalogApi, useProductEditor } from '@webx-ui/module-catalog'\nimport { screenErrorsKey } from '@webx-ui/schema'\nimport { createPropertiesApi } from './api'\nimport { fieldDecimals, formatNumber, propertyName, wordsIn } from './format'\nimport { NAMESPACE, useCatalogPropertiesMessages } from './i18n'\nimport type { EffectiveSet, HeldValue, PropertyRow } from './types'\nimport ValueSelect from './ValueSelect.vue'\nimport ValueTreeSelect from './ValueTreeSelect.vue'\n\n/**\n * `wx-catalog-product-properties`: the «Specifications» tab of a product (§7.2) — the field\n * `properties.values`, one control per property of the set of the product's **main** category,\n * by the groups of the card.\n *\n * The set is read again the moment the main category changes in the form, before anything is\n * saved: the server checks the set the product *will* have (§15, P2), so the tab has to show that\n * one. What the product holds of properties the new set does not have is dropped from what is\n * sent — not deleted: a key left out is not touched, and the value waits in the database for the\n * product to come back (decision 6).\n *\n * Those values are the collapsed block at the bottom, «Outside the category's set»: read only,\n * with one button that deletes them all — the bulk action `clear-outside-set` on this product.\n */\ndefineOptions({ name: 'WxCatalogProductProperties' })\n\ntype Values = Record<string, HeldValue>\n\nconst value = defineModel<Values | null>({ default: null })\n\n/* The refusal of the last save, to put each property's line under that property. */\nconst refusal = inject(screenErrorsKey, ref(undefined))\n\nconst admin = useAdmin()\nconst api = createPropertiesApi(admin)\nconst catalogApi = createCatalogApi(admin)\nconst editor = useProductEditor()\nconst locales = useLocales()\nuseCatalogPropertiesMessages()\n\nconst t = useTranslate(NAMESPACE)\nconst message = useErrorText()\n\nconst locale = computed(() => admin.i18n.state.locale)\nconst locked = computed(() => editor?.locked.value ?? false)\n/* Units are words of the site, per language: the one being edited, else the panel's. */\nconst unitLocale = computed(() => locales.active.value || locale.value)\n\nconst category = computed<number | null>(() => {\n const id = editor?.values?.value.category_id\n\n return typeof id === 'number' ? id : id ? Number(id) : null\n})\n\nconst set = ref<EffectiveSet | null>(null)\nconst loading = ref(false)\nconst failed = ref(false)\n\n/** Everything the product held when the editor last read it, in the set and out of it. */\nconst held = ref<Values>({})\nconst outsideNames = ref(new Map<number, PropertyRow>())\nconst outsideWords = ref(new Map<number, string>())\nconst clearing = ref(false)\n\nconst inSet = computed(\n () =>\n new Set((set.value?.groups ?? []).flatMap((group) => group.properties.map((one) => one.id))),\n)\n\n/** What the product holds of properties the set does not have. */\nconst outside = computed(() =>\n Object.entries(held.value)\n .filter(([id]) => !inSet.value.has(Number(id)))\n .map(([id, one]) => ({ id: Number(id), value: one })),\n)\n\n/* The editor read or saved the product: what it holds, all of it, is known again. */\nwatch(\n () => editor?.product.value,\n () => {\n const beyond = (editor?.values?.value['properties.outside'] ?? {}) as Values\n\n held.value = { ...(Array.isArray(beyond) ? {} : beyond), ...(value.value ?? {}) }\n },\n { immediate: true },\n)\n\n/**\n * The form's value for a new set: what was there for the properties that stay, what the product\n * held of the ones that come back, nothing for the ones that go. Written only when it differs, so\n * opening the tab does not mark the product unsaved.\n */\nfunction fit(): void {\n const next: Values = {}\n const now = value.value ?? {}\n\n for (const id of inSet.value) {\n const key = String(id)\n\n if (key in now) next[key] = now[key] ?? null\n else if (key in held.value) next[key] = held.value[key] ?? null\n }\n\n if (JSON.stringify(next) !== JSON.stringify(now)) value.value = next\n}\n\nlet asked = 0\n\nasync function loadSet(): Promise<void> {\n const ticket = ++asked\n\n if (category.value === null) {\n set.value = { groups: [] }\n fit()\n\n return\n }\n\n loading.value = true\n failed.value = false\n\n try {\n const answer = await api.effectiveSet(category.value)\n\n if (ticket !== asked) return\n set.value = answer\n fit()\n } catch {\n if (ticket === asked) failed.value = true\n } finally {\n if (ticket === asked) loading.value = false\n }\n}\n\nwatch(category, () => void loadSet(), { immediate: true })\n\n/* The block below names what it lists: the properties by one request, the values by one each. */\nwatch(\n outside,\n async (rows) => {\n const missing = rows.map((row) => row.id).filter((id) => !outsideNames.value.has(id))\n\n if (missing.length === 0) return\n\n try {\n const page = await api.list({ ids: missing })\n const names = new Map(outsideNames.value)\n\n for (const one of page.data) names.set(one.id, one)\n outsideNames.value = names\n\n const words = new Map(outsideWords.value)\n\n for (const row of rows) {\n const property = names.get(row.id)\n\n if (property) words.set(row.id, await wordsOf(property, row.value))\n }\n\n outsideWords.value = words\n } catch {\n // Named by number; the block is read only, and the button still does what it says.\n }\n },\n { immediate: true },\n)\n\nasync function wordsOf(property: PropertyRow, one: HeldValue): Promise<string> {\n if (one === null) return ''\n\n switch (property.type) {\n case 'select': {\n const ids = Array.isArray(one) ? (one as number[]) : [one as number]\n const values = await api.valuesById(property.id, ids)\n\n return values.map((row) => wordsIn(row.title, locale.value, `#${row.id}`)).join(', ')\n }\n case 'number':\n return formatNumber(\n Number(one),\n {\n precision: property.precision,\n prefix: wordsIn(property.unit_prefix, locale.value),\n suffix: wordsIn(property.unit_suffix, locale.value),\n },\n locale.value,\n )\n case 'bool':\n return t('product.yes')\n default:\n return wordsIn(one as LocalizedValue, locale.value)\n }\n}\n\nfunction read(id: number): HeldValue {\n return value.value?.[String(id)] ?? null\n}\n\nfunction write(id: number, next: HeldValue): void {\n const empty =\n next === null ||\n (Array.isArray(next) && next.length === 0) ||\n (typeof next === 'object' &&\n !Array.isArray(next) &&\n Object.values(next as LocalizedValue).every((line) => (line ?? '').trim() === ''))\n\n value.value = { ...(value.value ?? {}), [String(id)]: empty ? null : next }\n}\n\n/** A reference book's value: an id or a list of them. */\nfunction chosen(id: number): number | number[] | null {\n const one = read(id)\n\n return typeof one === 'number' || Array.isArray(one) ? (one as number | number[]) : null\n}\n\nfunction number(one: HeldValue): number | null {\n return typeof one === 'number' ? one : null\n}\n\nfunction text(one: HeldValue): LocalizedValue {\n return one && typeof one === 'object' && !Array.isArray(one) ? (one as LocalizedValue) : {}\n}\n\nfunction errorOf(id: number): string | undefined {\n const prefix = `properties.values.${id}`\n const errors = refusal.value ?? {}\n const key = Object.keys(errors).find((one) => one === prefix || one.startsWith(`${prefix}.`))\n\n return key === undefined ? undefined : errors[key]?.[0]\n}\n\nasync function clearOutside(): Promise<void> {\n const product = editor?.product.value\n\n if (!product) return\n\n const agreed = await confirm({\n title: t('panel.outside-clear-title'),\n message: t('panel.outside-clear-text'),\n confirmText: t('panel.delete'),\n cancelText: t('panel.cancel'),\n tone: 'danger',\n })\n\n if (!agreed) return\n\n clearing.value = true\n\n try {\n await catalogApi.startBulk('clear-outside-set', {}, { ids: [product.id] })\n\n const kept: Values = {}\n\n for (const [id, one] of Object.entries(held.value))\n if (inSet.value.has(Number(id))) kept[id] = one\n held.value = kept\n toast.success(t('panel.outside-cleared'))\n } catch (error) {\n toast.danger(message(error))\n } finally {\n clearing.value = false\n }\n}\n\nconst groupTitle = (group: EffectiveSet['groups'][number]) =>\n group.group ? wordsIn(group.group.title, locale.value) : ''\n</script>\n\n<template>\n <div class=\"wx-catalog-product-properties\">\n <wx-skeleton v-if=\"loading && !set\" :rows=\"4\" />\n\n <wx-alert\n v-else-if=\"failed\"\n type=\"warning\"\n variant=\"soft\"\n :description=\"t('panel.set-failed')\"\n />\n\n <template v-else-if=\"set\">\n <wx-alert\n v-if=\"category === null\"\n type=\"info\"\n variant=\"soft\"\n :description=\"t('panel.product-no-category')\"\n />\n <wx-alert\n v-else-if=\"set.groups.length === 0\"\n type=\"info\"\n variant=\"soft\"\n :description=\"t('panel.product-empty-set')\"\n />\n\n <section\n v-for=\"(group, index) in set.groups\"\n :key=\"group.group?.id ?? `none-${index}`\"\n class=\"wx-catalog-product-properties__group\"\n >\n <wx-text\n v-if=\"groupTitle(group)\"\n class=\"wx-catalog-product-properties__heading\"\n weight=\"semibold\"\n >\n {{ groupTitle(group) }}\n </wx-text>\n\n <!-- A switch names itself on its right, as \"Published\" does: a label above it is a line spent on one word. -->\n <wx-form-item\n v-for=\"property in group.properties\"\n :key=\"property.id\"\n :label=\"property.type === 'bool' ? undefined : propertyName(property, locale)\"\n :error=\"errorOf(property.id)\"\n >\n <value-tree-select\n v-if=\"property.type === 'select' && property.is_tree\"\n :property=\"property\"\n :model-value=\"chosen(property.id)\"\n :disabled=\"locked\"\n :aria-label=\"propertyName(property, locale)\"\n @update:model-value=\"(next) => write(property.id, next)\"\n />\n <value-select\n v-else-if=\"property.type === 'select'\"\n :property=\"property\"\n :model-value=\"chosen(property.id)\"\n :disabled=\"locked\"\n :aria-label=\"propertyName(property, locale)\"\n @update:model-value=\"(next) => write(property.id, next)\"\n />\n <span\n v-else-if=\"property.type === 'number'\"\n class=\"wx-catalog-product-properties__number\"\n >\n <span\n v-if=\"wordsIn(property.unit_prefix, unitLocale)\"\n class=\"wx-catalog-product-properties__unit\"\n >\n {{ wordsIn(property.unit_prefix, unitLocale) }}\n </span>\n <wx-input-number\n :model-value=\"number(read(property.id))\"\n :precision=\"fieldDecimals(property.precision, number(read(property.id)))\"\n :controls=\"false\"\n :disabled=\"locked\"\n :aria-label=\"propertyName(property, locale)\"\n @update:model-value=\"(next) => write(property.id, next ?? null)\"\n />\n <span\n v-if=\"wordsIn(property.unit_suffix, unitLocale)\"\n class=\"wx-catalog-product-properties__unit\"\n >\n {{ wordsIn(property.unit_suffix, unitLocale) }}\n </span>\n </span>\n <wx-switch\n v-else-if=\"property.type === 'bool'\"\n :model-value=\"read(property.id) === true\"\n :disabled=\"locked\"\n :label=\"propertyName(property, locale)\"\n @update:model-value=\"(on) => write(property.id, on ? true : null)\"\n />\n <wx-input\n v-else\n :model-value=\"text(read(property.id))\"\n localized\n :disabled=\"locked\"\n :aria-label=\"propertyName(property, locale)\"\n @update:model-value=\"(next) => write(property.id, next as LocalizedValue)\"\n />\n </wx-form-item>\n </section>\n\n <details v-if=\"outside.length > 0\" class=\"wx-catalog-product-properties__outside\">\n <summary>\n <wx-text weight=\"medium\">{{ t('panel.outside', { count: outside.length }) }}</wx-text>\n </summary>\n\n <wx-text size=\"sm\" tone=\"muted\">{{ t('panel.outside-help') }}</wx-text>\n\n <dl class=\"wx-catalog-product-properties__list\">\n <template v-for=\"row in outside\" :key=\"row.id\">\n <dt>\n {{\n outsideNames.get(row.id)\n ? propertyName(outsideNames.get(row.id)!, locale)\n : `#${row.id}`\n }}\n </dt>\n <dd>{{ outsideWords.get(row.id) ?? '…' }}</dd>\n </template>\n </dl>\n\n <wx-button\n v-if=\"!locked && admin.can('catalog.manage')\"\n size=\"sm\"\n variant=\"outline\"\n icon=\"trash\"\n :loading=\"clearing\"\n @click=\"clearOutside\"\n >\n {{ t('panel.outside-clear') }}\n </wx-button>\n </details>\n </template>\n </div>\n</template>\n\n<style scoped>\n/* Twice the step between fields, so a group reads as a group at every width. */\n.wx-catalog-product-properties {\n display: flex;\n flex-direction: column;\n gap: calc(var(--wx-gap, var(--wx-space-16)) * 2);\n}\n\n/* The step of every form in the panel, so the fields here keep the rhythm of the other tabs. */\n.wx-catalog-product-properties__group {\n display: flex;\n flex-direction: column;\n gap: var(--wx-gap, var(--wx-space-16));\n}\n\n.wx-catalog-product-properties__heading {\n padding-block-end: var(--wx-space-4);\n border-block-end: 1px solid var(--wx-border-muted);\n}\n\n.wx-catalog-product-properties__number {\n display: flex;\n align-items: center;\n gap: var(--wx-space-6);\n max-width: var(--wx-field-max-width, 480px);\n}\n\n.wx-catalog-product-properties__unit {\n flex: none;\n color: var(--wx-text-muted);\n white-space: pre;\n}\n\n.wx-catalog-product-properties__outside {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-8);\n padding: var(--wx-space-12);\n border: 1px solid var(--wx-border-muted);\n border-radius: var(--wx-radius-md);\n}\n\n.wx-catalog-product-properties__outside > summary {\n cursor: pointer;\n}\n\n.wx-catalog-product-properties__outside[open] > summary {\n margin-block-end: var(--wx-space-8);\n}\n\n.wx-catalog-product-properties__list {\n display: grid;\n grid-template-columns: minmax(0, max-content) minmax(0, 1fr);\n gap: var(--wx-space-4) var(--wx-space-16);\n margin: var(--wx-space-8) 0;\n color: var(--wx-text-muted);\n}\n\n.wx-catalog-product-properties__list dd {\n margin: 0;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { WxSelect, type SelectOption } from '@webx-ui/core'\nimport { usePropertyEditor } from './editor'\n\n/**\n * `wx-catalog-property-type`: the type of a property, chosen once (decision 1).\n *\n * A property that exists shows its type and does not let it change — the values of its products\n * have that shape, and «change the type» is a new property and a bulk move. The server refuses it\n * too (`errors.type-fixed`); the field says so before anybody tries. Without an editor above it —\n * a demo, a screen used for a new record — it is the select it looks like.\n */\ndefineOptions({ name: 'WxCatalogPropertyType', inheritAttrs: false })\n\nconst props = withDefaults(defineProps<{ options?: SelectOption[] }>(), { options: () => [] })\n\nconst value = defineModel<string | null>({ default: null })\n\nconst editor = usePropertyEditor()\n\nconst fixed = computed(() => (editor?.property.value?.id ?? null) !== null)\n</script>\n\n<template>\n <wx-select\n v-bind=\"$attrs\"\n v-model=\"value\"\n :options=\"props.options\"\n :disabled=\"fixed || undefined\"\n />\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref, watch } from 'vue'\nimport {\n useModal,\n WxAlert,\n WxButton,\n WxDialog,\n WxFormItem,\n WxSelect,\n WxSpace,\n type SelectOption,\n type SelectModelValue,\n} from '@webx-ui/core'\nimport { useAdmin, useErrorText, useTranslate } from '@webx-ui/module-admin'\nimport { createPropertiesApi } from './api'\nimport { wordsIn } from './format'\nimport { NAMESPACE } from './i18n'\nimport type { PropertyValue } from './types'\n\n/**\n * «Merge with…»: one value into another of the same property (§3.3). The products of the first\n * get the second, its slugs become the second's old addresses, and the first is gone — so before\n * anything happens the dialog says how many products that is, counted by the server's dry run.\n *\n * The target is found by search, because a reference book of colours or materials is long, and a\n * merge is done when two spellings of one thing are noticed — by name.\n */\ndefineOptions({ name: 'WxCatalogPropertyMergeDialog' })\n\nconst props = defineProps<{ property: number; value: PropertyValue }>()\n\nconst { open, resolve, dismiss } = useModal<number>()\n\nconst admin = useAdmin()\nconst api = createPropertiesApi(admin)\nconst t = useTranslate(NAMESPACE)\nconst message = useErrorText()\n\nconst locale = computed(() => admin.i18n.state.locale)\nconst name = computed(() => wordsIn(props.value.title, locale.value, `#${props.value.id}`))\n\nconst found = ref<PropertyValue[]>([])\nconst target = ref<number | null>(null)\nconst moved = ref<number | null>(null)\nconst counting = ref(false)\nconst merging = ref(false)\nconst failure = ref('')\n\nconst options = computed<SelectOption[]>(() =>\n found.value\n .filter((one) => one.id !== props.value.id)\n .map((one) => ({ value: one.id, label: wordsIn(one.title, locale.value, `#${one.id}`) })),\n)\n\nconst targetName = computed(\n () => options.value.find((option) => option.value === target.value)?.label ?? '',\n)\n\nlet asked = 0\n\nasync function search(term: string): Promise<void> {\n const ticket = ++asked\n\n try {\n const answer = await api.searchValues(props.property, term.trim(), 30)\n\n if (ticket === asked) found.value = answer\n } catch {\n if (ticket === asked) found.value = []\n }\n}\n\nvoid search('')\n\nwatch(target, async (into) => {\n moved.value = null\n failure.value = ''\n\n if (into === null) return\n\n counting.value = true\n\n try {\n moved.value = await api.mergeValue(props.property, props.value.id, into, true)\n } catch (error) {\n failure.value = message(error)\n } finally {\n counting.value = false\n }\n})\n\nfunction pick(value: SelectModelValue): void {\n target.value = typeof value === 'number' ? value : null\n}\n\nasync function merge(): Promise<void> {\n if (target.value === null || merging.value) return\n\n merging.value = true\n failure.value = ''\n\n try {\n resolve(await api.mergeValue(props.property, props.value.id, target.value))\n } catch (error) {\n failure.value = message(error)\n } finally {\n merging.value = false\n }\n}\n</script>\n\n<template>\n <wx-dialog v-model:open=\"open\" :title=\"t('panel.merge-title', { name })\" :width=\"480\">\n <wx-form-item :label=\"t('panel.merge-into')\" :help=\"t('panel.merge-help')\">\n <wx-select\n :model-value=\"target\"\n :options=\"options\"\n :placeholder=\"t('panel.search')\"\n :empty-text=\"t('panel.nothing-found')\"\n filterable\n @update:model-value=\"pick\"\n @search=\"search\"\n />\n </wx-form-item>\n\n <wx-alert v-if=\"failure\" type=\"danger\" variant=\"soft\" :description=\"failure\" />\n <wx-alert\n v-else-if=\"target !== null && moved !== null\"\n type=\"warning\"\n variant=\"soft\"\n :description=\"t('panel.merge-confirm', { name, target: targetName, count: moved })\"\n />\n\n <template #footer>\n <wx-space size=\"sm\">\n <wx-button variant=\"outline\" @click=\"dismiss()\">{{ t('panel.cancel') }}</wx-button>\n <wx-button\n type=\"primary\"\n :loading=\"merging || counting\"\n :disabled=\"target === null || moved === null\"\n @click=\"merge\"\n >\n {{ t('panel.merge') }}\n </wx-button>\n </wx-space>\n </template>\n </wx-dialog>\n</template>\n","<script setup lang=\"ts\">\nimport { nextTick, onMounted, ref, useTemplateRef } from 'vue'\nimport {\n useModal,\n WxButton,\n WxColorPicker,\n WxDialog,\n WxFormItem,\n WxInput,\n WxSpace,\n type LocalizedValue,\n} from '@webx-ui/core'\nimport { useAdmin, useTranslate } from '@webx-ui/module-admin'\nimport { openMediaPicker } from '@webx-ui/module-media'\nimport { createPropertiesApi, type ValueInput } from './api'\nimport { NAMESPACE } from './i18n'\nimport type { PropertyValue } from './types'\n\n/**\n * One value of a reference book: its name and its slug in every language the site publishes in —\n * the slug is the value in a filter's address, `/laptops/color_black/`, and is made of the name\n * where it is left empty (§3.4) — and its colour and its picture where the property has them. New\n * under `parent` when there is no `value`.\n *\n * The colour is data, not a style: the site's template decides how to draw it (§2). The picture is\n * one of the media library's, and wins over the colour on the storefront's swatch.\n */\ndefineOptions({ name: 'WxCatalogPropertyValueDialog' })\n\nconst props = withDefaults(\n defineProps<{\n property: number\n value?: PropertyValue | null\n parent?: number | null\n title: string\n color?: boolean\n image?: boolean\n }>(),\n { value: null, parent: null, color: false, image: false },\n)\n\nconst { open, resolve, dismiss } = useModal<PropertyValue>()\n\nconst api = createPropertiesApi(useAdmin())\nconst t = useTranslate(NAMESPACE)\n\nconst words = (map: PropertyValue['title'] | undefined): LocalizedValue =>\n map && !Array.isArray(map) ? { ...map } : {}\n\nconst name = ref<LocalizedValue>(words(props.value?.title))\nconst slug = ref<LocalizedValue>(words(props.value?.slug))\nconst color = ref<string | null>(props.value?.color ?? null)\nconst picture = ref<{ id: number; url: string } | null>(\n props.value?.image\n ? { id: props.value.image.id, url: props.value.image.thumb ?? props.value.image.url }\n : null,\n)\nconst saving = ref(false)\nconst errors = ref<Record<string, string[]>>({})\nconst field = useTemplateRef<HTMLElement>('field')\n\nonMounted(async () => {\n await nextTick()\n field.value?.querySelector('input')?.focus()\n})\n\nfunction errorOf(key: string): string | undefined {\n const found = Object.keys(errors.value).find((one) => one === key || one.startsWith(`${key}.`))\n\n return found === undefined ? undefined : errors.value[found]?.[0]\n}\n\nconst written = () => Object.values(name.value).some((line) => line.trim() !== '')\n\nasync function pick(): Promise<void> {\n const file = await openMediaPicker({ accept: 'image' })\n\n if (file) picture.value = { id: file.id, url: file.thumb ?? file.url }\n}\n\nasync function submit(): Promise<void> {\n if (!written() || saving.value) return\n\n saving.value = true\n errors.value = {}\n\n // What the property does not have is not sent: a value keeps its colour while the switch is off,\n // and turning it back on brings the colour back.\n const input: ValueInput = { title: name.value, slug: slug.value }\n\n if (props.color) input.color = color.value\n if (props.image) input.image_id = picture.value?.id ?? null\n\n try {\n resolve(\n props.value\n ? await api.saveValue(props.property, props.value.id, input)\n : await api.createValue(props.property, { ...input, parent_id: props.parent }),\n )\n } catch (error) {\n errors.value = (error as { body?: { errors?: Record<string, string[]> } }).body?.errors ?? {}\n } finally {\n saving.value = false\n }\n}\n</script>\n\n<template>\n <wx-dialog v-model:open=\"open\" :title=\"props.title\" :width=\"480\">\n <wx-form-item :label=\"t('value.title')\" :error=\"errorOf('title')\" required>\n <div ref=\"field\">\n <wx-input v-model=\"name\" localized :aria-label=\"t('value.title')\" @keyup.enter=\"submit\" />\n </div>\n </wx-form-item>\n\n <wx-form-item :label=\"t('value.slug')\" :help=\"t('panel.slug-help')\" :error=\"errorOf('slug')\">\n <wx-input v-model=\"slug\" localized :aria-label=\"t('value.slug')\" @keyup.enter=\"submit\" />\n </wx-form-item>\n\n <wx-form-item v-if=\"props.color\" :label=\"t('value.color')\" :error=\"errorOf('color')\">\n <wx-color-picker v-model=\"color\" clearable :aria-label=\"t('value.color')\" />\n </wx-form-item>\n\n <wx-form-item v-if=\"props.image\" :label=\"t('value.image')\" :error=\"errorOf('image_id')\">\n <div class=\"wx-catalog-value-dialog__picture\">\n <img v-if=\"picture\" :src=\"picture.url\" alt=\"\" />\n <wx-button size=\"sm\" variant=\"outline\" icon=\"image\" @click=\"pick\">\n {{ picture ? t('panel.picture-change') : t('panel.picture-pick') }}\n </wx-button>\n <wx-button v-if=\"picture\" size=\"sm\" variant=\"text\" @click=\"picture = null\">\n {{ t('panel.picture-remove') }}\n </wx-button>\n </div>\n </wx-form-item>\n\n <template #footer>\n <wx-space size=\"sm\">\n <wx-button variant=\"outline\" @click=\"dismiss()\">{{ t('panel.cancel') }}</wx-button>\n <wx-button type=\"primary\" :loading=\"saving\" :disabled=\"!written()\" @click=\"submit\">\n {{ props.value ? t('panel.save') : t('panel.create') }}\n </wx-button>\n </wx-space>\n </template>\n </wx-dialog>\n</template>\n\n<style scoped>\n.wx-catalog-value-dialog__picture {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--wx-space-8);\n}\n\n.wx-catalog-value-dialog__picture img {\n width: var(--wx-space-48);\n height: var(--wx-space-48);\n border-radius: var(--wx-radius-sm);\n object-fit: cover;\n box-shadow: inset 0 0 0 1px var(--wx-border-default);\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { useTranslate } from '@webx-ui/module-admin'\nimport { NAMESPACE } from './i18n'\nimport type { ValueNode } from './types'\n\n/**\n * What a value of the book looks like on its row: its picture or its colour — the picture wins,\n * as it does on the storefront's swatch — its name, its slug in the panel's language, and how\n * many products hold it: the number a refusal to delete names, said before anybody asks.\n */\ndefineOptions({ name: 'WxCatalogPropertyValueRow' })\n\nconst props = defineProps<{ node: ValueNode; locale: string }>()\n\nconst t = useTranslate(NAMESPACE)\n\nconst slug = computed(() => {\n const map = props.node.slug\n\n return map && !Array.isArray(map) ? (map[props.locale] ?? '') : ''\n})\n</script>\n\n<template>\n <span class=\"wx-catalog-value-row\">\n <img\n v-if=\"props.node.image\"\n class=\"wx-catalog-value-row__image\"\n :src=\"props.node.image.thumb ?? props.node.image.url\"\n alt=\"\"\n />\n <span\n v-else-if=\"props.node.color\"\n class=\"wx-catalog-value-row__swatch\"\n :style=\"{ background: props.node.color }\"\n aria-hidden=\"true\"\n />\n <span class=\"wx-catalog-value-row__title\">{{ props.node.label }}</span>\n <span v-if=\"slug\" class=\"wx-catalog-value-row__slug\">{{ slug }}</span>\n <span class=\"wx-catalog-value-row__count\">\n {{ t('panel.count', { count: props.node.products_count }) }}\n </span>\n </span>\n</template>\n\n<style scoped>\n.wx-catalog-value-row {\n display: flex;\n align-items: center;\n gap: var(--wx-space-8);\n width: 100%;\n min-width: 0;\n}\n\n.wx-catalog-value-row__swatch,\n.wx-catalog-value-row__image {\n flex: none;\n width: var(--wx-space-16);\n height: var(--wx-space-16);\n border-radius: var(--wx-radius-full);\n /* A white value on a white panel is still a circle. */\n box-shadow: inset 0 0 0 1px var(--wx-border-default);\n object-fit: cover;\n}\n\n.wx-catalog-value-row__title {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.wx-catalog-value-row__slug,\n.wx-catalog-value-row__count {\n flex: none;\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-sm);\n}\n\n/* At the end of the row, where the eye runs down a column of numbers. */\n.wx-catalog-value-row__count {\n margin-inline-start: auto;\n font-variant-numeric: tabular-nums;\n white-space: nowrap;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, ref, watch } from 'vue'\nimport {\n confirm,\n createModal,\n toast,\n WxAlert,\n WxButton,\n WxInput,\n WxSkeleton,\n WxText,\n WxTree,\n type TreeDropEvent,\n type TreeDropZone,\n} from '@webx-ui/core'\nimport {\n useAdmin,\n useErrorText,\n useTranslate,\n WxRowMenu,\n type RowAction,\n} from '@webx-ui/module-admin'\nimport { createPropertiesApi } from './api'\nimport { usePropertyEditor } from './editor'\nimport { wordsIn } from './format'\nimport { NAMESPACE, useCatalogPropertiesMessages } from './i18n'\nimport MergeDialog from './MergeDialog.vue'\nimport type { PropertyValue, ValueNode } from './types'\nimport ValueDialog from './ValueDialog.vue'\nimport ValueRow from './ValueRow.vue'\n\n/**\n * `wx-catalog-property-values`: the reference book of a property (§7.1, «Values»).\n *\n * A tree that reads one branch at a time (`WxTree` with `lazy`, which is `useTreeNodes` under\n * it): a book of materials three levels deep or of a thousand car models is opened where it is\n * needed, not all at once. A search answers flat, at any depth.\n *\n * A row shows the colour or the picture, the name, the slug and how many products hold the value;\n * the first three are written in the value's dialog — a colour picker on every row of a long book\n * is a column of controls nobody reads. Every change is a request of its own and is saved at once:\n * the values are records, not fields of the form (the editor's button saves «Main»). By hand, the\n * order and the nesting are dragged; in alphabetical order nothing is, because the alphabet decides.\n *\n * A value products hold is not deleted: the refusal says how many, and the way out is «Merge\n * with…», which moves those products onto another value first.\n */\ndefineOptions({ name: 'WxCatalogPropertyValues' })\n\nconst admin = useAdmin()\nconst api = createPropertiesApi(admin)\nconst editor = usePropertyEditor()\nuseCatalogPropertiesMessages()\n\nconst t = useTranslate(NAMESPACE)\nconst message = useErrorText()\n\nconst property = computed(() => editor?.property.value ?? null)\nconst id = computed(() => property.value?.id ?? null)\nconst locale = computed(() => admin.i18n.state.locale)\nconst locked = computed(() => editor?.locked.value ?? true)\n\n/* The colour and the picture follow the switches as they are flipped; the order and the nesting\n follow what is saved, because that is what the server orders and nests by. */\nconst hasColor = computed(() => Boolean(editor?.values.value.has_color))\nconst hasImage = computed(() => Boolean(editor?.values.value.has_image))\nconst isTree = computed(() => property.value?.is_tree ?? false)\nconst manual = computed(() => property.value?.value_order === 'manual')\n\nconst roots = ref<ValueNode[]>([])\nconst expanded = ref<(string | number)[]>([])\nconst loading = ref(true)\nconst failed = ref(false)\n\nconst query = ref('')\nconst found = ref<ValueNode[] | null>(null)\nconst searching = computed(() => query.value.trim() !== '')\n\nconst draft = ref('')\nconst adding = ref(false)\n\nconst draggable = computed(() => !locked.value && manual.value && !searching.value)\n\nconst editValue = createModal<\n PropertyValue,\n {\n property: number\n value?: PropertyValue | null\n parent?: number | null\n title: string\n color?: boolean\n image?: boolean\n }\n>(ValueDialog)\nconst mergeValue = createModal<number, { property: number; value: PropertyValue }>(MergeDialog)\n\nfunction nodeOf(value: PropertyValue): ValueNode {\n return {\n ...value,\n label: wordsIn(value.title, locale.value, `#${value.id}`),\n leaf: !value.has_children,\n children: undefined,\n }\n}\n\nasync function load(): Promise<void> {\n if (id.value === null) return\n\n loading.value = true\n failed.value = false\n\n try {\n roots.value = (await api.values(id.value)).map(nodeOf)\n expanded.value = []\n } catch {\n failed.value = true\n } finally {\n loading.value = false\n }\n}\n\nwatch(id, () => void load(), { immediate: true })\n\n/* A new order or tree setting changes what the server answers with — the branches are read again. */\nwatch(\n () => [property.value?.value_order, property.value?.is_tree],\n (now, before) => {\n if (before !== undefined && (now[0] !== before[0] || now[1] !== before[1])) void load()\n },\n)\n\nasync function loadBranch(node: ValueNode): Promise<ValueNode[]> {\n if (id.value === null) return []\n\n return (await api.values(id.value, node.id)).map(nodeOf)\n}\n\nlet timer: ReturnType<typeof setTimeout> | undefined\nlet asked = 0\n\nwatch(query, (term) => {\n clearTimeout(timer)\n\n if (term.trim() === '') {\n found.value = null\n\n return\n }\n\n timer = setTimeout(async () => {\n if (id.value === null) return\n\n const ticket = ++asked\n\n try {\n const answer = (await api.searchValues(id.value, term.trim(), 100)).map((value) => ({\n ...nodeOf(value),\n leaf: true,\n }))\n\n if (ticket === asked) found.value = answer\n } catch {\n if (ticket === asked) found.value = []\n }\n }, 250)\n})\n\nonBeforeUnmount(() => clearTimeout(timer))\n\n/** Every loaded node with this id — a value can be on screen in the tree and in a search. */\nfunction each(fn: (node: ValueNode) => void, nodes: ValueNode[] = roots.value): void {\n for (const node of nodes) {\n fn(node)\n if (node.children) each(fn, node.children)\n }\n\n if (nodes === roots.value && found.value) for (const node of found.value) fn(node)\n}\n\nfunction replace(value: PropertyValue): void {\n each((node) => {\n if (node.id === value.id) {\n Object.assign(node, {\n ...value,\n label: wordsIn(value.title, locale.value, `#${value.id}`),\n leaf: !value.has_children && !(node.children && node.children.length > 0),\n children: node.children,\n })\n }\n })\n}\n\nfunction refused(error: unknown): void {\n toast.danger(message(error))\n}\n\n/** A new value at the top level, by its name in the panel's language — the row above the tree. */\nasync function add(): Promise<void> {\n const title = draft.value.trim()\n\n if (title === '' || id.value === null || adding.value) return\n\n adding.value = true\n\n try {\n const made = nodeOf(await api.createValue(id.value, { title: { [locale.value]: title } }))\n\n draft.value = ''\n roots.value = manual.value\n ? [...roots.value, made]\n : [...roots.value, made].sort((a, b) => a.label.localeCompare(b.label, locale.value))\n } catch (error) {\n refused(error)\n } finally {\n adding.value = false\n }\n}\n\nasync function addInside(parent: ValueNode): Promise<void> {\n if (id.value === null) return\n\n const made = await editValue({\n property: id.value,\n parent: parent.id,\n title: t('panel.value-new-inside', { name: parent.label }),\n color: hasColor.value,\n image: hasImage.value,\n })\n\n if (made === undefined) return\n\n // A branch that was never opened reads its children when it is; one that was gets the new one.\n if (parent.children) parent.children.push(nodeOf(made))\n parent.has_children = true\n parent.leaf = false\n if (!expanded.value.includes(parent.id)) expanded.value = [...expanded.value, parent.id]\n}\n\nasync function edit(node: ValueNode): Promise<void> {\n if (id.value === null) return\n\n const saved = await editValue({\n property: id.value,\n value: node,\n title: node.label,\n color: hasColor.value,\n image: hasImage.value,\n })\n\n if (saved !== undefined) replace(saved)\n}\n\nasync function merge(node: ValueNode): Promise<void> {\n if (id.value === null) return\n\n const moved = await mergeValue({ property: id.value, value: node })\n\n if (moved === undefined) return\n\n toast.success(t('panel.merged', { count: moved }))\n query.value = ''\n await load()\n}\n\nasync function remove(node: ValueNode): Promise<void> {\n if (id.value === null) return\n\n if (node.products_count > 0) {\n toast.warning(t('panel.value-in-use', { count: node.products_count }))\n\n return\n }\n\n const agreed = await confirm({\n title: t('panel.value-delete-title', { name: node.label }),\n message: node.has_children ? t('panel.value-delete-branch') : t('panel.value-delete-text'),\n confirmText: t('panel.delete'),\n cancelText: t('panel.cancel'),\n tone: 'danger',\n })\n\n if (!agreed) return\n\n try {\n await api.removeValue(id.value, node.id)\n // Out of whatever array holds it, the tree's and the search's alike.\n const prune = (nodes: ValueNode[]): ValueNode[] =>\n nodes\n .filter((one) => one.id !== node.id)\n .map((one) => (one.children ? Object.assign(one, { children: prune(one.children) }) : one))\n\n roots.value = prune(roots.value)\n if (found.value) found.value = prune(found.value)\n } catch (error) {\n const products = (error as { body?: { meta?: { products?: number } } }).body?.meta?.products\n\n if (products) toast.warning(t('panel.value-in-use', { count: products }))\n else refused(error)\n }\n}\n\nfunction menuOf(node: ValueNode): RowAction[] {\n if (locked.value) return []\n\n const items: RowAction[] = [\n { key: 'edit', label: t('panel.edit'), icon: 'edit', run: () => void edit(node) },\n ]\n\n if (isTree.value && !searching.value) {\n items.push({\n key: 'inside',\n label: t('panel.value-add-inside'),\n icon: 'plus',\n run: () => void addInside(node),\n })\n }\n\n items.push(\n { key: 'merge', label: t('panel.merge-with'), icon: 'copy', run: () => void merge(node) },\n {\n key: 'delete',\n label: t('panel.delete'),\n icon: 'trash',\n danger: true,\n run: () => void remove(node),\n },\n )\n\n return items\n}\n\n/* Only a tree takes a value inside another; a flat book is a list, and only its order moves. */\nfunction allowDrop(_drag: ValueNode, _drop: ValueNode, zone: TreeDropZone): boolean {\n return isTree.value || zone !== 'inside'\n}\n\n/**\n * The tree has already moved the node on screen; this tells the server where it landed — under\n * which parent, before which sibling — and reads the tree again if it did not agree.\n */\nasync function moved(event: TreeDropEvent<ValueNode>): Promise<void> {\n if (id.value === null) return\n\n const siblings = event.parent ? (event.parent.children ?? []) : roots.value\n const before = siblings[event.index + 1] ?? null\n\n if (event.parent) {\n event.parent.has_children = true\n event.parent.leaf = false\n }\n\n try {\n await api.moveValue(id.value, event.node.id, event.parent?.id ?? null, before?.id ?? null)\n } catch (error) {\n refused(error)\n await load()\n }\n}\n</script>\n\n<template>\n <div class=\"wx-catalog-values\">\n <wx-alert\n v-if=\"!property\"\n type=\"info\"\n variant=\"soft\"\n :description=\"t('panel.values-unsaved')\"\n />\n\n <template v-else>\n <div class=\"wx-catalog-values__bar\">\n <form v-if=\"!locked\" class=\"wx-catalog-values__add\" @submit.prevent=\"add\">\n <wx-input\n v-model=\"draft\"\n :placeholder=\"t('panel.value-new')\"\n :aria-label=\"t('panel.value-new')\"\n size=\"sm\"\n />\n <wx-button\n native-type=\"submit\"\n size=\"sm\"\n :loading=\"adding\"\n :disabled=\"draft.trim() === ''\"\n >\n {{ t('panel.add') }}\n </wx-button>\n </form>\n\n <wx-input\n v-model=\"query\"\n class=\"wx-catalog-values__search\"\n :placeholder=\"t('panel.search')\"\n :aria-label=\"t('panel.search')\"\n clearable\n size=\"sm\"\n />\n </div>\n\n <wx-skeleton v-if=\"loading\" :rows=\"4\" />\n\n <wx-alert\n v-else-if=\"failed\"\n type=\"warning\"\n variant=\"soft\"\n :description=\"t('panel.values-failed')\"\n />\n\n <wx-tree\n v-else-if=\"searching\"\n :model-value=\"found ?? []\"\n class=\"wx-catalog-values__tree\"\n :empty-text=\"found === null ? t('panel.searching') : t('panel.nothing-found')\"\n :aria-label=\"t('property.tab-values')\"\n >\n <template #default=\"{ node }\">\n <value-row :node=\"node as ValueNode\" :locale=\"locale\" />\n </template>\n <template #actions=\"{ node }\">\n <wx-row-menu\n v-if=\"!locked\"\n :actions=\"menuOf(node as ValueNode)\"\n :label=\"(node as ValueNode).label\"\n />\n </template>\n </wx-tree>\n\n <wx-tree\n v-else\n v-model=\"roots\"\n v-model:expanded=\"expanded\"\n class=\"wx-catalog-values__tree\"\n lazy\n :load=\"loadBranch\"\n leaf-key=\"leaf\"\n :draggable=\"draggable\"\n :allow-drop=\"allowDrop\"\n :empty-text=\"t('panel.values-empty')\"\n :aria-label=\"t('property.tab-values')\"\n @drop=\"moved\"\n >\n <template #default=\"{ node }\">\n <value-row :node=\"node as ValueNode\" :locale=\"locale\" />\n </template>\n <template #actions=\"{ node }\">\n <wx-row-menu\n v-if=\"!locked\"\n :actions=\"menuOf(node as ValueNode)\"\n :label=\"(node as ValueNode).label\"\n />\n </template>\n </wx-tree>\n\n <wx-text v-if=\"!loading && !failed && !searching\" size=\"sm\" tone=\"muted\">\n {{ manual ? t('panel.values-order-manual') : t('panel.values-order-alpha') }}\n </wx-text>\n </template>\n </div>\n</template>\n\n<style scoped>\n.wx-catalog-values {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-12);\n container-type: inline-size;\n}\n\n.wx-catalog-values__bar {\n display: flex;\n flex-wrap: wrap;\n gap: var(--wx-space-8);\n}\n\n.wx-catalog-values__add {\n display: flex;\n flex: 1 1 280px;\n gap: var(--wx-space-8);\n min-width: 0;\n}\n\n.wx-catalog-values__add > :first-child {\n flex: 1 1 auto;\n min-width: 0;\n}\n\n.wx-catalog-values__search {\n flex: 0 1 240px;\n min-width: 0;\n}\n\n/* On a phone the two lines stand one over the other, each the whole width. */\n@container (max-width: 520px) {\n .wx-catalog-values__search {\n flex-basis: 100%;\n }\n}\n</style>\n","import { defineComponent, h, type Component } from 'vue'\nimport type { RouteRecordRaw } from 'vue-router'\nimport {\n categoryRoutes,\n type AdminModule,\n type CategoriesOptions,\n type CategoryWord,\n} from '@webx-ui/module-admin'\nimport { GROUPS_API } from './api'\nimport CategoryPropertiesField from './CategoryPropertiesField.vue'\nimport { NAMESPACE, useCatalogPropertiesMessages } from './i18n'\nimport IntervalsField from './IntervalsField.vue'\nimport NumberExample from './NumberExample.vue'\nimport ProductPropertiesField from './ProductPropertiesField.vue'\nimport TypeField from './TypeField.vue'\nimport ValuesField from './ValuesField.vue'\n\nexport interface CatalogPropertiesOptions {\n /** Where the catalogue lives inside the panel — the same as `catalog({ path })`. */\n path?: string\n}\n\n/** The words of the shared category screens the groups say in their own way. */\nconst GROUP_WORDS: CategoryWord[] = [\n 'new',\n 'empty',\n 'empty-help',\n 'order',\n 'hidden',\n 'count',\n 'delete-blocked',\n 'delete-text',\n 'deleted',\n 'saved',\n]\n\n/**\n * The groups of the card — «Screen», «Processor» — as the panel's shared category screens see\n * them: a flat list in the order of the card, and the page of one, which is the server's\n * `catalog.property-group-form`. Not an entry of the navigation: they are reached from the head\n * of the properties and lead back there.\n */\nexport function propertyGroupsOptions(options: CatalogPropertiesOptions = {}): CategoriesOptions {\n const catalog = options.path ?? '/catalog'\n\n return {\n api: GROUPS_API,\n path: `${catalog}/properties/groups`,\n name: 'webx.catalog-properties.groups',\n module: 'catalog-properties',\n title: `${NAMESPACE}::panel.groups-title`,\n back: { path: `${catalog}/properties`, label: `${NAMESPACE}::module.title` },\n screen: 'catalog.property-group-form',\n manage: 'catalog.manage',\n count: 'properties_count',\n words: Object.fromEntries(GROUP_WORDS.map((word) => [word, `${NAMESPACE}::group.${word}`])),\n }\n}\n\n/**\n * The shared screens run nothing of this package's before they draw, so the route puts its\n * English under the panel's dictionary first — as the catalogue's reference books do.\n */\nfunction seeded(route: RouteRecordRaw): RouteRecordRaw {\n const page = (route as { component?: Component }).component\n\n if (page === undefined) return route\n\n return {\n ...route,\n component: defineComponent({\n name: 'WxCatalogPropertyGroupsView',\n setup() {\n useCatalogPropertiesMessages()\n\n return () => h(page)\n },\n }),\n } as RouteRecordRaw\n}\n\n/**\n * The properties of products as a section of the panel (§7 of the properties spec): the list,\n * the page of one property with its values and intervals, and their groups behind a button.\n * «Catalog» → «Dictionaries» → «Properties» on the server's side (order 312).\n *\n * The node types are the rest of it: the tab «Properties» of a category (its set) and the tab\n * «Specifications» of a product — both patched onto the catalogue's screens by the server — and\n * the parts of the property's own screen that a form field cannot be.\n */\nexport function catalogProperties(options: CatalogPropertiesOptions = {}): AdminModule[] {\n const catalog = options.path ?? '/catalog'\n const props = { base: catalog }\n\n return [\n {\n id: 'catalog-properties',\n path: `${catalog}/properties`,\n routes: [\n {\n path: `${catalog}/properties`,\n name: 'webx.catalog-properties',\n component: () => import('./PropertiesPage.vue'),\n props,\n },\n {\n path: `${catalog}/properties/:id(\\\\d+)`,\n name: 'webx.catalog-properties.edit',\n component: () => import('./PropertyEditorPage.vue'),\n props,\n },\n ...categoryRoutes(propertyGroupsOptions(options)).map(seeded),\n ],\n types: {\n 'wx-catalog-property-type': { component: TypeField, kind: 'field' },\n 'wx-catalog-property-example': { component: NumberExample, kind: 'display' },\n 'wx-catalog-property-values': { component: ValuesField, kind: 'display' },\n 'wx-catalog-property-intervals': { component: IntervalsField, kind: 'display' },\n 'wx-catalog-category-properties': { component: CategoryPropertiesField, kind: 'display' },\n // Wide: a group of the card is a column of fields, and half a form is too narrow for a\n // combobox of values beside its label.\n 'wx-catalog-product-properties': {\n component: ProductPropertiesField,\n kind: 'field',\n wide: true,\n },\n },\n },\n ]\n}\n","import { defineAsyncComponent } from 'vue'\nimport './style.css'\n\nexport { catalogProperties, propertyGroupsOptions, type CatalogPropertiesOptions } from './module'\nexport { catalogPropertiesMessages } from './messages'\nexport {\n createPropertiesApi,\n propertySearch,\n GROUPS_API,\n PROPERTIES_API,\n SETS_API,\n type CatalogPropertiesApi,\n type ValueInput,\n} from './api'\nexport { formatNumber, propertyName, wordsIn, type NumberShape } from './format'\nexport {\n propertyEditorKey,\n providePropertyEditor,\n usePropertyEditor,\n type PropertyEditorContext,\n} from './editor'\nexport const WxCatalogPropertiesPage = defineAsyncComponent(() => import('./PropertiesPage.vue'))\nexport const WxCatalogPropertyEditor = defineAsyncComponent(\n () => import('./PropertyEditorPage.vue'),\n)\nexport { default as WxCatalogPropertyValues } from './ValuesField.vue'\nexport { default as WxCatalogPropertyIntervals } from './IntervalsField.vue'\nexport { default as WxCatalogCategoryProperties } from './CategoryPropertiesField.vue'\nexport { default as WxCatalogProductProperties } from './ProductPropertiesField.vue'\nexport type {\n CategorySet,\n EffectiveSet,\n FilterMode,\n HeldValue,\n PropertiesPage,\n PropertyDetail,\n PropertyInterval,\n PropertyQuery,\n PropertyRow,\n PropertyType,\n PropertyValue,\n ValueNode,\n ValueOrder,\n Words,\n} from './types'\n"],"names":["PROPERTIES_API","GROUPS_API","SETS_API","propertySearch","query","search","id","createPropertiesApi","admin","base","data","body","withQuery","path","values","ids","intervals","interval","title","slug","min","max","parent","q","perPage","one","input","value","before","into","dryRun","category","wordsIn","words","locale","fallback","localizedValue","propertyName","property","formatNumber","shape","digits","number","exampleNumber","precision","fieldDecimals","held","own","catalogPropertiesMessages","NAMESPACE","seeded","useCatalogPropertiesMessages","i18n","useAdmin","api","editor","useCatalogCategoryEditor","useTranslate","message","useErrorText","computed","locked","set","ref","all","loading","failed","saving","picked","taken","row","offered","take","answer","load","page","watch","now","save","error","first","toast","add","remove","reorder","typeOf","_openBlock","_createElementBlock","_hoisted_1","_createBlock","_unref","WxAlert","WxSkeleton","_Fragment","_createVNode","WxText","_hoisted_2","_renderList","_createElementVNode","_hoisted_3","_toDisplayString","_createTextVNode","WxSortableList","$event","_withCtx","item","_hoisted_4","_hoisted_5","WxButton","WxSelect","propertyEditorKey","providePropertyEditor","provide","usePropertyEditor","inject","rows","snapshot","errors","made","map","rowOf","list","dirty","last","key","sortByBounds","low","high","a","b","errorOf","index","field","prefix","saved","WxInput","WxInputNumber","line","WxAction","locales","useLocales","t","example","CREATE","props","__props","_useModel","canCreate","known","found","term","creating","chosen","remember","next","exact","typed","label","options","missing","timer","asked","text","ticket","onBeforeUnmount","create","name","pick","rest","_cache","roots","paths","nodeOf","loadRoots","named","selectedPath","node","WxTreeSelect","refusal","screenErrorsKey","catalogApi","createCatalogApi","useProductEditor","unitLocale","outsideNames","outsideWords","clearing","inSet","group","outside","beyond","fit","loadSet","names","wordsOf","read","write","empty","clearOutside","product","confirm","kept","groupTitle","WxFormItem","ValueTreeSelect","ValueSelect","WxSwitch","on","_hoisted_6","fixed","_mergeProps","_ctx","open","resolve","dismiss","useModal","target","moved","counting","merging","failure","targetName","option","merge","WxDialog","WxSpace","color","picture","useTemplateRef","onMounted","nextTick","written","file","openMediaPicker","submit","WxColorPicker","_normalizeStyle","hasColor","hasImage","isTree","manual","expanded","searching","draft","adding","draggable","editValue","createModal","ValueDialog","mergeValue","MergeDialog","loadBranch","each","fn","nodes","replace","refused","addInside","edit","prune","products","menuOf","items","allowDrop","_drag","_drop","zone","event","WxTree","ValueRow","WxRowMenu","GROUP_WORDS","propertyGroupsOptions","catalog","word","route","defineComponent","h","catalogProperties","categoryRoutes","TypeField","NumberExample","ValuesField","IntervalsField","CategoryPropertiesField","ProductPropertiesField","WxCatalogPropertiesPage","defineAsyncComponent","WxCatalogPropertyEditor"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -3,8 +3,20 @@ export { catalogPropertiesMessages } from './messages';
|
|
|
3
3
|
export { createPropertiesApi, propertySearch, GROUPS_API, PROPERTIES_API, SETS_API, type CatalogPropertiesApi, type ValueInput, } from './api';
|
|
4
4
|
export { formatNumber, propertyName, wordsIn, type NumberShape } from './format';
|
|
5
5
|
export { propertyEditorKey, providePropertyEditor, usePropertyEditor, type PropertyEditorContext, } from './editor';
|
|
6
|
-
export
|
|
7
|
-
|
|
6
|
+
export declare const WxCatalogPropertiesPage: import('vue').DefineComponent<{
|
|
7
|
+
base?: string;
|
|
8
|
+
}, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<{
|
|
9
|
+
base?: string;
|
|
10
|
+
}> & Readonly<{}>, {
|
|
11
|
+
base: string;
|
|
12
|
+
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLDivElement>;
|
|
13
|
+
export declare const WxCatalogPropertyEditor: import('vue').DefineComponent<{
|
|
14
|
+
base?: string;
|
|
15
|
+
}, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<{
|
|
16
|
+
base?: string;
|
|
17
|
+
}> & Readonly<{}>, {
|
|
18
|
+
base: string;
|
|
19
|
+
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLDivElement>;
|
|
8
20
|
export { default as WxCatalogPropertyValues } from './ValuesField';
|
|
9
21
|
export { default as WxCatalogPropertyIntervals } from './IntervalsField';
|
|
10
22
|
export { default as WxCatalogCategoryProperties } from './CategoryPropertiesField';
|