@wssto2/vue-core 0.16.0 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -0
- package/README.md +4 -3
- package/bin/architecture/engine.mjs +3 -0
- package/bin/architecture/permissions.mjs +56 -0
- package/bin/architecture/rules.mjs +17 -0
- package/bin/commands/check-architecture.mjs +19 -0
- package/bin/config.mjs +2 -0
- package/dist/{AccessGate.vue_vue_type_script_setup_true_lang-BH3f0hda.js → AccessGate.vue_vue_type_script_setup_true_lang-Bg8JFAOT.js} +1 -1
- package/dist/{ActionRow.vue_vue_type_script_setup_true_lang-DybAIOHS.js → ActionRow.vue_vue_type_script_setup_true_lang-B5IMNnTf.js} +4 -4
- package/dist/{Activity-DOUuIkZR.js → Activity-CiYn5E6A.js} +7 -7
- package/dist/{AdaptivePageShell.vue_vue_type_script_setup_true_lang-d_dPurWG.js → AdaptivePageShell.vue_vue_type_script_setup_true_lang-oXWQTfBs.js} +1 -1
- package/dist/{Changes-BfcbVgmu.js → Changes-Cy8STpLX.js} +3 -3
- package/dist/{CollectionPage.vue_vue_type_script_setup_true_lang-B5hSkJ2N.js → CollectionPage.vue_vue_type_script_setup_true_lang-Dr6nFNBB.js} +6 -6
- package/dist/{DataTable.vue_vue_type_script_setup_true_lang-DbRS37n3.js → DataTable.vue_vue_type_script_setup_true_lang-D372wlxR.js} +1 -1
- package/dist/{DateField.vue_vue_type_script_setup_true_lang-DzCvYHAf.js → DateField.vue_vue_type_script_setup_true_lang-D0KcfW8R.js} +17 -16
- package/dist/{DeadLetters-CuMvfXH8.js → DeadLetters-DhJkMpd_.js} +4 -4
- package/dist/{FormGroup.vue_vue_type_script_setup_true_lang-dsO1m9Mm.js → FormGroup.vue_vue_type_script_setup_true_lang-lvAuBG-0.js} +2 -2
- package/dist/FormRow.vue_vue_type_script_setup_true_lang-CpgNVQF4.js +160 -0
- package/dist/{FormView.vue_vue_type_script_setup_true_lang-Bq_Qa4py.js → FormView.vue_vue_type_script_setup_true_lang-D01Jr4UU.js} +5 -5
- package/dist/{General-B5vcSEhP.js → General-CwTPC5UP.js} +10 -10
- package/dist/{IncidentRecord-wmStcEag.js → IncidentRecord-hXEGuLGg.js} +13 -13
- package/dist/{IncidentsList-CFx5tsxP.js → IncidentsList-C41VyDwK.js} +6 -6
- package/dist/{NewRolePage-CZxAp7LR.js → NewRolePage-BYYZJkK7.js} +3 -3
- package/dist/{NumberField.vue_vue_type_script_setup_true_lang-U-_kcnGr.js → NumberField.vue_vue_type_script_setup_true_lang-BhNZgEW6.js} +7 -6
- package/dist/{PersonAccess.vue_vue_type_script_setup_true_lang-BPDh9s2m.js → PersonAccess.vue_vue_type_script_setup_true_lang-mYFuG-Y3.js} +56 -56
- package/dist/{ProfilePage-B-T8kBcc.js → ProfilePage-DGEsIycR.js} +13 -13
- package/dist/{RecordHeader.vue_vue_type_script_setup_true_lang-Bt5mT19g.js → RecordHeader.vue_vue_type_script_setup_true_lang-B3BnYg1x.js} +1 -1
- package/dist/{ResourcePage.vue_vue_type_script_setup_true_lang-DOiFuJnH.js → ResourcePage.vue_vue_type_script_setup_true_lang-1iZtj3rh.js} +1 -1
- package/dist/{RoleEditor.vue_vue_type_script_setup_true_lang-CqSsNPCw.js → RoleEditor.vue_vue_type_script_setup_true_lang-BslSDDiM.js} +9 -9
- package/dist/{RolePage-zcUWpuDE.js → RolePage-C08ZUqw1.js} +9 -9
- package/dist/{RolesPage-C7_zWw-c.js → RolesPage-FOuY1VKg.js} +10 -10
- package/dist/{SectionNavigator.vue_vue_type_script_setup_true_lang-BlCx9dVL.js → SectionNavigator.vue_vue_type_script_setup_true_lang-DCTFxfPB.js} +2 -2
- package/dist/{SegmentedField.vue_vue_type_script_setup_true_lang-zv_AxpBn.js → SegmentedField.vue_vue_type_script_setup_true_lang-CLR6EvzO.js} +13 -12
- package/dist/{SelectField.vue_vue_type_script_setup_true_lang-CLkoPbGm.js → SelectField.vue_vue_type_script_setup_true_lang-D5xYofdb.js} +10 -9
- package/dist/{ServiceAccountDialog.vue_vue_type_script_setup_true_lang-C2D_D5Hi.js → ServiceAccountDialog.vue_vue_type_script_setup_true_lang-CDr4WNIb.js} +9 -9
- package/dist/{ServiceAccountRecord-BYxpHzTR.js → ServiceAccountRecord-kWwIQGZb.js} +12 -12
- package/dist/{ServiceAccountsList-BUuK-RUj.js → ServiceAccountsList-CKy9_YHP.js} +8 -8
- package/dist/{Sessions-Cm-Kilwl.js → Sessions-BDc8gdYH.js} +4 -4
- package/dist/{SettingsPage-Bavl0K-F.js → SettingsPage-t-8kmFVT.js} +13 -13
- package/dist/{SignIn-SfEhFiyM.js → SignIn-CqtkvtCZ.js} +7 -7
- package/dist/{SignInPage-BU0n2ehq.js → SignInPage-DcdNKZIb.js} +4 -4
- package/dist/{SignIns-Ahbn5cO6.js → SignIns-D4-nGu0B.js} +3 -3
- package/dist/{SwitchField.vue_vue_type_script_setup_true_lang-Ds4q0bbl.js → SwitchField.vue_vue_type_script_setup_true_lang-CLtcuofe.js} +15 -14
- package/dist/{TextField.vue_vue_type_script_setup_true_lang-CWIeeZRE.js → TextField.vue_vue_type_script_setup_true_lang-CVGh-p3J.js} +7 -6
- package/dist/{TextareaField.vue_vue_type_script_setup_true_lang-D2j4s96s.js → TextareaField.vue_vue_type_script_setup_true_lang-YxUlNHSk.js} +6 -5
- package/dist/{TimeField.vue_vue_type_script_setup_true_lang-C1mLvOkc.js → TimeField.vue_vue_type_script_setup_true_lang-DHNC_MLt.js} +30 -29
- package/dist/{Timestamp.vue_vue_type_script_setup_true_lang-jCXYFLtq.js → Timestamp.vue_vue_type_script_setup_true_lang-d_KuxWjH.js} +1 -1
- package/dist/{UserRecord-3pCKMHkq.js → UserRecord-CwZCr9Im.js} +10 -10
- package/dist/{UsersList-vw3aDpvo.js → UsersList-Cn19sFgv.js} +4 -4
- package/dist/access/index.js +4 -4
- package/dist/app/application.d.ts +2 -0
- package/dist/app/index.js +2 -2
- package/dist/app/validate.d.ts +3 -1
- package/dist/{application-CHPpOssP.js → application-CDSweJb9.js} +144 -142
- package/dist/collection/authors.d.ts +27 -0
- package/dist/collection/index.d.ts +2 -0
- package/dist/collection/index.js +81 -76
- package/dist/config/index.d.ts +42 -0
- package/dist/config/index.js +12 -3
- package/dist/content/Panel.vue.d.ts +1 -1
- package/dist/content/index.js +2 -2
- package/dist/{contributions-9CPT-Z5v.js → contributions-B0x5x5xD.js} +1 -1
- package/dist/form/CommandDialog.vue.d.ts +1 -1
- package/dist/form/DateField.vue.d.ts +1 -1
- package/dist/form/DateTimeField.vue.d.ts +1 -1
- package/dist/form/FileField.vue.d.ts +1 -1
- package/dist/form/FormRow.vue.d.ts +2 -2
- package/dist/form/I18nField.vue.d.ts +2 -2
- package/dist/form/TextField.vue.d.ts +1 -1
- package/dist/form/TextareaField.vue.d.ts +2 -2
- package/dist/form/date/value.d.ts +21 -0
- package/dist/form/index.d.ts +1 -0
- package/dist/form/index.js +745 -715
- package/dist/format/format.d.ts +8 -2
- package/dist/format/index.js +1 -1
- package/dist/format-C_HXlOYQ.js +136 -0
- package/dist/{guards-6fJxfUtk.js → guards-CNJ0ATVC.js} +1 -1
- package/dist/i18n/index.d.ts +14 -2
- package/dist/i18n/index.js +84 -73
- package/dist/i18n/messages.d.ts +10 -1
- package/dist/i18n/runtime.d.ts +3 -1
- package/dist/identity/index.js +3 -3
- package/dist/identity/profile/EmailChangeDialog.vue.d.ts +2 -2
- package/dist/identity/users/list.d.ts +1 -1
- package/dist/incidents/index.js +1 -1
- package/dist/{index-D9_xqF5g.js → index-1HS7O2-e.js} +9 -9
- package/dist/{index-nByFc1eL.js → index-BA2w8uwD.js} +86 -86
- package/dist/{index-Ct7W_gYE.js → index-SLJWm40T.js} +4 -4
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/modal/DiscardChangesModal.vue.d.ts +2 -2
- package/dist/modal/Modal.vue.d.ts +2 -2
- package/dist/modal/Sheet.vue.d.ts +2 -2
- package/dist/modules/identity/routes.d.ts +1 -1
- package/dist/modules/identity/schemas.d.ts +2 -2
- package/dist/{navigation-DMJ6akat.js → navigation-d-JAPBGA.js} +1 -1
- package/dist/{neighbors-BpypL3Wb.js → neighbors-Dg_LU9ry.js} +1 -1
- package/dist/notifications/index.js +1 -1
- package/dist/onboarding/index.js +1 -1
- package/dist/options-mOOX6JSS.js +214 -0
- package/dist/overlay/AlertDialog.vue.d.ts +3 -3
- package/dist/overlay/Menu.vue.d.ts +2 -2
- package/dist/overlay/PhotoViewer.vue.d.ts +2 -2
- package/dist/overlay/Popover.vue.d.ts +2 -2
- package/dist/page/SectionNavigator.vue.d.ts +1 -1
- package/dist/page/SectionPanel.vue.d.ts +1 -1
- package/dist/page/index.js +3 -3
- package/dist/phone/index.js +57 -56
- package/dist/platform/index.d.ts +10 -1
- package/dist/platform/index.js +16 -15
- package/dist/platform/platform.d.ts +4 -2
- package/dist/{platform-ORzRR3Tw.js → platform-DU9QFts8.js} +7 -6
- package/dist/playwright/config.d.ts +33 -0
- package/dist/playwright/index.d.ts +2 -0
- package/dist/playwright/index.js +192 -171
- package/dist/resource/index.js +1 -1
- package/dist/router/index.js +3 -3
- package/dist/{rowLayout-QKfNHsML.js → rowLayout-PIuD7MGo.js} +2 -2
- package/dist/{sections-CSpJN0Z7.js → sections-BpiRLntE.js} +1 -1
- package/dist/{serverMessages-Ce8-MK4e.js → serverMessages-C_KkDvpT.js} +1 -1
- package/dist/shell/index.js +4 -4
- package/dist/state/NextStepPanel.vue.d.ts +63 -0
- package/dist/state/PhaseTiles.vue.d.ts +20 -0
- package/dist/state/PhaseTrack.vue.d.ts +48 -0
- package/dist/state/RequirementList.vue.d.ts +10 -0
- package/dist/state/TodoRow.vue.d.ts +52 -0
- package/dist/state/index.d.ts +9 -0
- package/dist/state/index.js +731 -126
- package/dist/state/phaseStep.d.ts +7 -0
- package/dist/state/phaseTile.d.ts +10 -0
- package/dist/state/requirementItem.d.ts +16 -0
- package/dist/state/todoRow.d.ts +8 -0
- package/dist/{state-QDaxntgR.js → state-z1iPF1DT.js} +1 -1
- package/dist/styles.css +1 -1
- package/dist/{suggestions-q_v3M7G6.js → suggestions-DeMgs_ki.js} +1 -1
- package/dist/testing/format.d.ts +1 -1
- package/dist/testing/index.js +31 -31
- package/dist/{useCommand-DAMgQ5NE.js → useCommand-DQKvro1n.js} +2 -2
- package/dist/{useGroupSheet-B-Hs4gNO.js → useGroupSheet-CRw3MUmX.js} +3 -3
- package/dist/{usePreferences-BfMXVbSO.js → usePreferences-DB29UTFD.js} +1 -1
- package/dist/{useRecordDialog-QPKFH1Ww.js → useRecordDialog-0azHxxvm.js} +1 -1
- package/dist/{useResourceForm-Oa6bk3NI.js → useResourceForm-zVuWerSn.js} +1 -1
- package/dist/{useTypedEntry-CITij2C_.js → useTypedEntry-BsMV66Yc.js} +46 -45
- package/package.json +1 -1
- package/dist/format-Cp1h0vsC.js +0 -125
- package/dist/options-B48UiYsG.js +0 -368
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.17.0 — 2026-11-04
|
|
4
|
+
|
|
5
|
+
What every app built on vue-core wrote again: the phase and to-do components, date values in the date fields' own shape, a lazy locale loader, the author of a list row, "today at 14:35", typed access, two architecture rules as data, and the Playwright and vitest setup. Breaking only in that `Platform.access` is now typed by the registered permissions (see Changed).
|
|
6
|
+
|
|
7
|
+
### New
|
|
8
|
+
- **state:** `PhaseTrack`, `PhaseTiles`, `TodoRow`, `NextStepPanel`, `RequirementList` and their types (`PhaseStep`, `PhaseTile`, `PhaseTone`, `RequirementItem`, `TodoRowAction`, `TodoRowState`): where a record stands, what is next, and what is still missing. New texts `core.stepper`, `core.next_step`, `core.requirements`, `core.todo_state`, `core.phase_tiles` in the five locales. Recipe: `docs/recipes/workflow.md`.
|
|
9
|
+
- **i18n:** `localeMessages(namespace, import.meta.glob("./*.json"))`, still lazy: nothing loads until the namespace is needed. A file's locale is its name; `createApplication({ localeFiles: { bs: "ba" } })` renames the exceptions.
|
|
10
|
+
- **form:** `dateValue(api)` (`YYYY-MM-DD`, sliced as written), `dateTimeValue(api)` (`YYYY-MM-DDTHH:mm` in local time, the shape `DateTimeField` writes), `parseDateValue(model)` (the `T` and the space form, as local time), `now()`; `today()` is exported. Go's zero date is `null`.
|
|
11
|
+
- **collection:** `authorOf(meta, id)`, `ResourceAuthor`, `ResourceMeta`, for go-core's `meta.authors` / `meta.author` / `meta.editor`.
|
|
12
|
+
- **format:** `format.when(value)`: just now, minutes ago, today / yesterday / tomorrow at a time, else the date and time. New texts `core.when.*`.
|
|
13
|
+
- **platform:** `useAccess()`. An application registers its generated permissions once (`interface PermissionRegistry extends Record<Permission, true> {}`); `useAccess()`, `Platform.access`, route meta `access` and `AccessGate` then refuse an unknown permission at compile time, template literals over a namespace type included.
|
|
14
|
+
- **devkit:** `check-architecture` rule `permission-texts` (`architecture.permissions: { generated, keys, locales, dir }`): every generated permission has each key (`policies.{id}`, `policy_descriptions.{id}`) in each locale, and no locale keeps a text for one that is gone.
|
|
15
|
+
- **devkit:** `architecture.forbidden: [{ id, pattern, message, exclude? }]`: text rules as data. Comments are stripped (a `//` in a string or URL is kept), tests, e2e, docs and scripts are skipped by default, and each rule has its allowlist `allow[id]`.
|
|
16
|
+
- **playwright:** `playwrightConfig({ testDir, timezone, ignore, port, report }, overrides)`: `E2E_PORT`, the dev server, CI retries and workers, the reporters plus the JSON report `vue-core e2e-timings` reads, and the time zone for the specs and the browser.
|
|
17
|
+
- **config:** `vitestDefaults({ timezone, setupFiles })` for the vitest `test` block: globals, happy-dom, `e2e/` and `review/` excluded, `TZ` pinned.
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
- **platform:** `Platform.access` is `AccessClient<Permission>`, the registered permissions. Code that assigned it to a narrower `AccessClient<X>` registers `X` instead.
|
|
21
|
+
- **format:** `Formatting.translate` receives the message parameters.
|
|
22
|
+
|
|
3
23
|
## 0.16.0 — 2026-10-22
|
|
4
24
|
|
|
5
25
|
Back to the page a record was opened from.
|
package/README.md
CHANGED
|
@@ -116,8 +116,8 @@ export function createTicketsFeature(http: HttpClient) {
|
|
|
116
116
|
id: "tickets",
|
|
117
117
|
routes: ticketRoutes.records,
|
|
118
118
|
context: provideContext(TICKETS, { api, list: createTicketList(api) }),
|
|
119
|
-
// Loaded the first time a route of this feature is entered, in the active locale.
|
|
120
|
-
messages: localeMessages("tickets",
|
|
119
|
+
// Loaded the first time a route of this feature is entered, in the active locale. The lazy glob takes the file names as locales (en.json, hr.json); `createApplication({ localeFiles: { bs: "ba" } })` renames the exceptions.
|
|
120
|
+
messages: localeMessages("tickets", import.meta.glob("./i18n/*.json")),
|
|
121
121
|
// The backend's menu names destinations; this says which route opens "tickets" and which records keep it highlighted.
|
|
122
122
|
navigation: [{ destination: "tickets", to: ticketRoutes.index, within: ["tickets.record"] }],
|
|
123
123
|
});
|
|
@@ -327,7 +327,7 @@ Dark mode is the `dark` class on `<html>`; nothing is decided for you. An app th
|
|
|
327
327
|
|
|
328
328
|
## Texts and locales
|
|
329
329
|
|
|
330
|
-
The library's own texts are under the `core` namespace in English, Croatian, Bosnian and Slovenian (`t("core.actions.cancel")`). `createApplication` merges them into its vue-i18n instance; override any key with `i18n.messages` and restrict the offered locales with `locale.supported`. A feature's texts are a namespace (`localeMessages("tickets",
|
|
330
|
+
The library's own texts are under the `core` namespace in English, Croatian, Bosnian and Slovenian (`t("core.actions.cancel")`). `createApplication` merges them into its vue-i18n instance; override any key with `i18n.messages` and restrict the offered locales with `locale.supported`. A feature's texts are a namespace (`localeMessages("tickets", import.meta.glob("./i18n/*.json"))`, or one `() => import("./i18n/en.json")` per locale; used as `t("tickets.title")`) loaded per locale on demand. A locale switch (the account menu has one) loads every namespace in use first, so nothing shows a raw key; `locale.onChange` lets you save the choice on the user.
|
|
331
331
|
|
|
332
332
|
## Recipes
|
|
333
333
|
|
|
@@ -345,6 +345,7 @@ The library's own texts are under the `core` namespace in English, Croatian, Bos
|
|
|
345
345
|
- [Notifications](docs/recipes/notifications.md): the bell, the inbox and the live stream, categories, the failed-events page, trying it against go-core's dev server
|
|
346
346
|
- [Incidents](docs/recipes/incidents.md): go-core's incident module: the list and an incident, "Report a bug", the browser's errors reported (what is and is not sent), source maps
|
|
347
347
|
- [Preferences and tips](docs/recipes/preferences.md): `usePreferences`, the person's stored settings, `darkMode()` on them, the `Tip` beside something new
|
|
348
|
+
- [Where a record stands](docs/recipes/workflow.md): `PhaseTrack`, `PhaseTiles`, `TodoRow`, `NextStepPanel`, `RequirementList` in `/state`
|
|
348
349
|
- [Theming](docs/recipes/theming.md): brand accent, dark mode, tokens, status tones and category hues
|
|
349
350
|
- [Testing](docs/recipes/testing.md): the application's environment and a fake backend for your tests
|
|
350
351
|
- [End-to-end specs](docs/recipes/e2e.md): `@wssto2/vue-core/playwright`, the Playwright mocks of go-core's envelope, session, access, notification, profile and users routes
|
|
@@ -4,6 +4,7 @@ import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
|
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
|
|
6
6
|
import { PACKS } from "./packs.mjs";
|
|
7
|
+
import { checkPermissionTexts } from "./permissions.mjs";
|
|
7
8
|
import { builtInRules } from "./rules.mjs";
|
|
8
9
|
|
|
9
10
|
const SOURCE_EXTENSIONS = new Set([".ts", ".vue"]);
|
|
@@ -142,6 +143,8 @@ export function check({ root, config, configName }) {
|
|
|
142
143
|
}
|
|
143
144
|
}
|
|
144
145
|
|
|
146
|
+
if (config.permissions) violations.push(...checkPermissionTexts({ root, config: config.permissions }));
|
|
147
|
+
|
|
145
148
|
// every directory name under the features folder is a single lowercase word
|
|
146
149
|
for (const dirPath of collectFeatureDirs(featuresRoot)) {
|
|
147
150
|
const rel = toPosix(path.relative(root, dirPath));
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// permission-texts: the permissions the generated catalogue lists and the texts the locale files keep for them agree. Every id has each key
|
|
2
|
+
// in each locale, and no locale keeps a key for an id that is gone. A key template is `<namespace>.<prefix>{id}`: the namespace is the folder
|
|
3
|
+
// `<dir>/<namespace>/<locale>.json`, and the file is nested by dots (`"crm": { "lead:view": "…" }` holds `crm.lead:view`).
|
|
4
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
|
|
7
|
+
/** The ids of a generated permissions file: its quoted strings (`export type Permission = 'a:view' | 'b:view'`), comments cut out. */
|
|
8
|
+
export function generatedIds(source) {
|
|
9
|
+
const code = source.replace(/\/\*[\s\S]*?\*\//g, "").replace(/(^|[^:"'`])\/\/.*$/gm, "$1");
|
|
10
|
+
// Only the `Permission` union names ids; go-core's generator writes a metadata map after it, full of other strings.
|
|
11
|
+
const union = /export\s+type\s+Permission\s*=([^;]*);/.exec(code);
|
|
12
|
+
if (!union) throw new Error("permission-texts: the generated file has no `export type Permission = …;` union");
|
|
13
|
+
return [...new Set([...union[1].matchAll(/(["'`])([^"'`\n]+)\1/g)].map((match) => match[2]))];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// A nested messages file as the identifiers it holds: a leaf string is named by the dotted path to it.
|
|
17
|
+
function flatten(node, prefix, out) {
|
|
18
|
+
for (const [key, value] of Object.entries(node)) {
|
|
19
|
+
if (typeof value === "string") out.add(prefix + key);
|
|
20
|
+
else if (value && typeof value === "object") flatten(value, `${prefix}${key}.`, out);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** The violations of `permission-texts`, as messages that start with the file they concern. */
|
|
25
|
+
export function checkPermissionTexts({ root, config: { generated, keys, locales, dir = "i18n" } }) {
|
|
26
|
+
const generatedFile = path.join(root, generated);
|
|
27
|
+
if (!existsSync(generatedFile)) return [`${generated}: permission-texts — the generated permissions file does not exist.`];
|
|
28
|
+
const ids = generatedIds(readFileSync(generatedFile, "utf8"));
|
|
29
|
+
const known = new Set(ids);
|
|
30
|
+
const violations = [];
|
|
31
|
+
for (const locale of locales) {
|
|
32
|
+
for (const key of keys) {
|
|
33
|
+
const [namespace, ...rest] = key.split(".");
|
|
34
|
+
const prefix = rest.join(".").replace("{id}", "");
|
|
35
|
+
const file = `${dir}/${namespace}/${locale}.json`;
|
|
36
|
+
if (!existsSync(path.join(root, file))) {
|
|
37
|
+
violations.push(`${file}: permission-texts — the file does not exist.`);
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
let messages;
|
|
41
|
+
try {
|
|
42
|
+
messages = JSON.parse(readFileSync(path.join(root, file), "utf8"));
|
|
43
|
+
} catch (error) {
|
|
44
|
+
violations.push(`${file}: permission-texts — not valid JSON (${error.message}).`);
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
const have = new Set();
|
|
48
|
+
flatten(messages, "", have);
|
|
49
|
+
for (const id of ids) if (!have.has(prefix + id)) violations.push(`${file}: permission-texts — ${id} has no text (${key.replace("{id}", id)}).`);
|
|
50
|
+
for (const name of [...have].sort()) {
|
|
51
|
+
if (name.startsWith(prefix) && !known.has(name.slice(prefix.length))) violations.push(`${file}: permission-texts — ${name.slice(prefix.length)} is not in ${generated}; remove its text.`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return violations;
|
|
56
|
+
}
|
|
@@ -81,6 +81,22 @@ function noRoutePolicy({ sessionField, exclude }) {
|
|
|
81
81
|
};
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
+
/**
|
|
85
|
+
* forbidden: the application's own text rules as data. The first line of the file (comments cut out, tests never scanned, and by default
|
|
86
|
+
* not the e2e / review / scripts / tests / docs / templates / static folders) that `pattern` matches. `exclude` replaces that folder default.
|
|
87
|
+
*/
|
|
88
|
+
function forbiddenRule({ pattern, message, exclude = PLAIN_SOURCE }) {
|
|
89
|
+
return ({ file, content, isTest }) => {
|
|
90
|
+
if (isTest || matches(exclude, file)) return null;
|
|
91
|
+
const hit = withoutComments(content)
|
|
92
|
+
.split("\n")
|
|
93
|
+
.find((line) => matches(pattern, line));
|
|
94
|
+
return hit ? `“${hit.trim().slice(0, 80)}” — ${message}` : null;
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const PLAIN_SOURCE = /^(e2e|review|scripts|tests|docs|templates|static)\//;
|
|
99
|
+
|
|
84
100
|
export const RULE_IDS = ["no-hardcoded-copy", "no-route-policy"];
|
|
85
101
|
|
|
86
102
|
/** The rules the config switches on, each `{ id, check, seen }` (`seen`: the allowlisted files that tripped it). */
|
|
@@ -91,5 +107,6 @@ export function builtInRules(config) {
|
|
|
91
107
|
rules.push({ id: "no-hardcoded-copy", check: noHardcodedCopy({ ...config.copy, scope }) });
|
|
92
108
|
}
|
|
93
109
|
if (config.routeAccess) rules.push({ id: "no-route-policy", check: noRoutePolicy(config.routeAccess) });
|
|
110
|
+
for (const rule of config.forbidden) rules.push({ id: rule.id, check: forbiddenRule(rule) });
|
|
94
111
|
return rules.map((rule) => ({ ...rule, seen: new Set() }));
|
|
95
112
|
}
|
|
@@ -20,10 +20,29 @@ export default function run({ config, root, configPath, err }) {
|
|
|
20
20
|
const packRules = [
|
|
21
21
|
...settings.packs.filter((name) => Object.hasOwn(PACKS, name)).flatMap((name) => PACKS[name].rules.map((rule) => rule.id)),
|
|
22
22
|
...RULE_IDS.filter((id) => (id === "no-hardcoded-copy" ? settings.copy : settings.routeAccess)),
|
|
23
|
+
...settings.forbidden.map((rule) => rule.id),
|
|
23
24
|
];
|
|
24
25
|
if (settings.copy && !(settings.copy.pattern instanceof RegExp)) problems.push("copy.pattern: a regular expression for the language's letters and words, e.g. /[čćžšđ]|\\b(Spremi|Odustani)\\b/");
|
|
25
26
|
for (const key of ["scope", "properNames"]) if (settings.copy?.[key] !== undefined && !(settings.copy[key] instanceof RegExp)) problems.push(`copy.${key}: must be a regular expression`);
|
|
26
27
|
if (settings.routeAccess?.exclude !== undefined && !(settings.routeAccess.exclude instanceof RegExp)) problems.push("routeAccess.exclude: must be a regular expression");
|
|
28
|
+
const ids = new Set([...RULE_IDS, ...ALLOW_RULES, "permission-texts"]);
|
|
29
|
+
for (const [index, rule] of settings.forbidden.entries()) {
|
|
30
|
+
const at = `forbidden[${index}]`;
|
|
31
|
+
if (typeof rule?.id !== "string" || rule.id === "") problems.push(`${at}.id: a rule name, used in the message and the allowlist`);
|
|
32
|
+
else if (ids.has(rule.id)) problems.push(`${at}.id: "${rule.id}" is a built-in rule's name`);
|
|
33
|
+
else ids.add(rule.id);
|
|
34
|
+
if (!(rule?.pattern instanceof RegExp)) problems.push(`${at}.pattern: must be a regular expression`);
|
|
35
|
+
if (typeof rule?.message !== "string" || rule.message === "") problems.push(`${at}.message: what to do instead`);
|
|
36
|
+
if (rule?.exclude !== undefined && !(rule.exclude instanceof RegExp)) problems.push(`${at}.exclude: must be a regular expression`);
|
|
37
|
+
}
|
|
38
|
+
const texts = settings.permissions;
|
|
39
|
+
if (texts) {
|
|
40
|
+
if (typeof texts.generated !== "string") problems.push("permissions.generated: the generated permissions file, relative to the config's folder");
|
|
41
|
+
if (!Array.isArray(texts.keys) || texts.keys.length === 0 || !texts.keys.every((key) => typeof key === "string" && key.includes("{id}") && key.includes("."))) {
|
|
42
|
+
problems.push('permissions.keys: message keys with {id}, "<namespace>.{id}", e.g. ["policies.{id}", "policy_descriptions.{id}"]');
|
|
43
|
+
}
|
|
44
|
+
if (!Array.isArray(texts.locales) || texts.locales.length === 0) problems.push('permissions.locales: the locale file names, e.g. ["hr", "en"]');
|
|
45
|
+
}
|
|
27
46
|
for (const rule of Object.keys(settings.allow)) {
|
|
28
47
|
if (!ALLOW_RULES.includes(rule) && !packRules.includes(rule)) problems.push(`allow.${rule}: no such rule; the allowlists are ${[...ALLOW_RULES, ...packRules].join(", ")}`);
|
|
29
48
|
}
|
package/bin/config.mjs
CHANGED
|
@@ -32,6 +32,8 @@ export const DEFAULTS = {
|
|
|
32
32
|
doc: {},
|
|
33
33
|
copy: null,
|
|
34
34
|
routeAccess: null,
|
|
35
|
+
forbidden: [],
|
|
36
|
+
permissions: null,
|
|
35
37
|
},
|
|
36
38
|
generator: { template: join(dirname(fileURLToPath(import.meta.url)), "templates", "feature-crud"), out: "features" },
|
|
37
39
|
e2eTimings: { report: "e2e-timings/results.json" },
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { defineComponent as r, openBlock as o, createElementBlock as l, createElementVNode as s, toDisplayString as n, createCommentVNode as d, renderSlot as f, createBlock as u, unref as c, withCtx as p, normalizeClass as _, createVNode as x } from "vue";
|
|
2
|
-
import {
|
|
2
|
+
import { _ as b } from "./FormRow.vue_vue_type_script_setup_true_lang-CpgNVQF4.js";
|
|
3
3
|
import { _ as h } from "./Icon.vue_vue_type_script_lang-BhhsFYwp.js";
|
|
4
|
-
const k = { class: "flex flex-wrap items-end gap-3 px-row-inset" },
|
|
4
|
+
const k = { class: "flex flex-wrap items-end gap-3 px-row-inset" }, w = { class: "flex min-w-0 grow basis-56 flex-col gap-1" }, g = { class: "text-title font-semibold tracking-tight text-content-strong" }, y = {
|
|
5
5
|
key: 0,
|
|
6
6
|
class: "max-w-readable text-subheadline text-content-muted"
|
|
7
7
|
}, E = /* @__PURE__ */ r({
|
|
@@ -12,8 +12,8 @@ const k = { class: "flex flex-wrap items-end gap-3 px-row-inset" }, g = { class:
|
|
|
12
12
|
},
|
|
13
13
|
setup(e) {
|
|
14
14
|
return (i, t) => (o(), l("div", k, [
|
|
15
|
-
s("div",
|
|
16
|
-
s("h2",
|
|
15
|
+
s("div", w, [
|
|
16
|
+
s("h2", g, n(e.title), 1),
|
|
17
17
|
e.description ? (o(), l("p", y, n(e.description), 1)) : d("", !0)
|
|
18
18
|
]),
|
|
19
19
|
f(i.$slots, "actions")
|
|
@@ -3,18 +3,18 @@ import { useI18n as D } from "vue-i18n";
|
|
|
3
3
|
import { RouterLink as I } from "vue-router";
|
|
4
4
|
import { _ as T } from "./IconTile.vue_vue_type_script_setup_true_lang-BmxCuUZ9.js";
|
|
5
5
|
import { _ as z } from "./Tabs.vue_vue_type_script_setup_true_lang-tpkGp98F.js";
|
|
6
|
-
import { u as G } from "./format-
|
|
7
|
-
import { _ as B } from "./DateField.vue_vue_type_script_setup_true_lang-
|
|
8
|
-
import { a as H } from "./FormGroup.vue_vue_type_script_setup_true_lang-
|
|
9
|
-
import {
|
|
6
|
+
import { u as G } from "./format-C_HXlOYQ.js";
|
|
7
|
+
import { _ as B } from "./DateField.vue_vue_type_script_setup_true_lang-D0KcfW8R.js";
|
|
8
|
+
import { a as H } from "./FormGroup.vue_vue_type_script_setup_true_lang-lvAuBG-0.js";
|
|
9
|
+
import { _ as J } from "./FormRow.vue_vue_type_script_setup_true_lang-CpgNVQF4.js";
|
|
10
10
|
import { i as M } from "./preferences-hYhrw8Uy.js";
|
|
11
|
-
import { u as Q } from "./platform-
|
|
11
|
+
import { u as Q } from "./platform-DU9QFts8.js";
|
|
12
12
|
import { b as W } from "./routeResource-DlTsGTg_.js";
|
|
13
13
|
import { _ as X } from "./AsyncSection.vue_vue_type_script_setup_true_lang-CX8mpXRE.js";
|
|
14
14
|
import { _ as Y } from "./Badge.vue_vue_type_script_setup_true_lang-DJyZc0C7.js";
|
|
15
15
|
import { u as Z } from "./useLoad-M7V-AVwR.js";
|
|
16
|
-
import { P as tt, f as et, j as at } from "./index-
|
|
17
|
-
import { _ as st } from "./ActionRow.vue_vue_type_script_setup_true_lang-
|
|
16
|
+
import { P as tt, f as et, j as at } from "./index-BA2w8uwD.js";
|
|
17
|
+
import { _ as st } from "./ActionRow.vue_vue_type_script_setup_true_lang-B5IMNnTf.js";
|
|
18
18
|
const ot = {
|
|
19
19
|
class: "flex min-w-0 flex-col gap-group-gap",
|
|
20
20
|
"data-person-activity": ""
|
|
@@ -6,7 +6,7 @@ import { _ as Q } from "./Button.vue_vue_type_script_setup_true_lang-JrqhO99l.js
|
|
|
6
6
|
import { _ as $ } from "./Icon.vue_vue_type_script_lang-BhhsFYwp.js";
|
|
7
7
|
import { _ as U } from "./Menu.vue_vue_type_script_setup_true_lang-Cqu4Ebsb.js";
|
|
8
8
|
import { RouterLink as E, useRoute as W } from "vue-router";
|
|
9
|
-
import { u as Y } from "./format-
|
|
9
|
+
import { u as Y } from "./format-C_HXlOYQ.js";
|
|
10
10
|
import { u as F, c as G, p as J } from "./chrome-kMBKIB1N.js";
|
|
11
11
|
import { b as X } from "./back-LcLlFodC.js";
|
|
12
12
|
import { d as Z } from "./context-Ch1r4fdN.js";
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { defineComponent as h, ref as m, watch as p, openBlock as l, createElementBlock as d, createVNode as c, unref as t, withCtx as y, toDisplayString as x, createBlock as f, createCommentVNode as k } from "vue";
|
|
2
2
|
import { useI18n as C } from "vue-i18n";
|
|
3
3
|
import { i as $ } from "./preferences-hYhrw8Uy.js";
|
|
4
|
-
import { u as b } from "./platform-
|
|
4
|
+
import { u as b } from "./platform-DU9QFts8.js";
|
|
5
5
|
import { b as V } from "./routeResource-DlTsGTg_.js";
|
|
6
6
|
import { _ as R } from "./AsyncSection.vue_vue_type_script_setup_true_lang-CX8mpXRE.js";
|
|
7
7
|
import { u as E } from "./useLoad-M7V-AVwR.js";
|
|
8
|
-
import { P as N, f as B, k as P, j as S } from "./index-
|
|
9
|
-
import { _ as U } from "./ActionRow.vue_vue_type_script_setup_true_lang-
|
|
8
|
+
import { P as N, f as B, k as P, j as S } from "./index-BA2w8uwD.js";
|
|
9
|
+
import { _ as U } from "./ActionRow.vue_vue_type_script_setup_true_lang-B5IMNnTf.js";
|
|
10
10
|
import { _ as I } from "./ViewTabs.vue_vue_type_script_setup_true_lang-BjdDXE3T.js";
|
|
11
11
|
const W = {
|
|
12
12
|
class: "flex min-w-0 flex-col gap-group-gap",
|
|
@@ -2,22 +2,22 @@ import { hasInjectionContext as lt, inject as ot, shallowRef as xe, computed as
|
|
|
2
2
|
import { routerKey as ct } from "vue-router";
|
|
3
3
|
import { i as qe, a as ut } from "./error-CD7x0Jrz.js";
|
|
4
4
|
import { d as dt } from "./http-D6qOS6xs.js";
|
|
5
|
-
import { d as Re, o as ft, L as Te, e as je, w as pt, r as vt } from "./state-
|
|
6
|
-
import { _ as mt } from "./AdaptivePageShell.vue_vue_type_script_setup_true_lang-
|
|
5
|
+
import { d as Re, o as ft, L as Te, e as je, w as pt, r as vt } from "./state-z1iPF1DT.js";
|
|
6
|
+
import { _ as mt } from "./AdaptivePageShell.vue_vue_type_script_setup_true_lang-oXWQTfBs.js";
|
|
7
7
|
import { useI18n as he } from "vue-i18n";
|
|
8
8
|
import { _ as ce } from "./Button.vue_vue_type_script_setup_true_lang-JrqhO99l.js";
|
|
9
9
|
import { _ as Ge } from "./Tabs.vue_vue_type_script_setup_true_lang-tpkGp98F.js";
|
|
10
|
-
import { u as Pe } from "./format-
|
|
10
|
+
import { u as Pe } from "./format-C_HXlOYQ.js";
|
|
11
11
|
import { _ as I } from "./Icon.vue_vue_type_script_lang-BhhsFYwp.js";
|
|
12
12
|
import { _ as Ne } from "./Banner.vue_vue_type_script_setup_true_lang-sv0phngk.js";
|
|
13
13
|
import { _ as Ae } from "./EmptyState.vue_vue_type_script_setup_true_lang-DbZiO2RF.js";
|
|
14
|
-
import { u as bt, _ as gt } from "./rowLayout-
|
|
14
|
+
import { u as bt, _ as gt } from "./rowLayout-PIuD7MGo.js";
|
|
15
15
|
import { u as Ee } from "./shortcut-oixX55SZ.js";
|
|
16
16
|
import { _ as Ye } from "./Menu.vue_vue_type_script_setup_true_lang-Cqu4Ebsb.js";
|
|
17
17
|
import { _ as Ze } from "./Popover.vue_vue_type_script_setup_true_lang-BK8HL_V0.js";
|
|
18
18
|
import { _ as we } from "./ToneDot.vue_vue_type_script_setup_true_lang-99rNn-L5.js";
|
|
19
|
-
import { _ as ht } from "./NumberField.vue_vue_type_script_setup_true_lang-
|
|
20
|
-
import { _ as yt } from "./SelectField.vue_vue_type_script_setup_true_lang-
|
|
19
|
+
import { _ as ht } from "./NumberField.vue_vue_type_script_setup_true_lang-BhNZgEW6.js";
|
|
20
|
+
import { _ as yt } from "./SelectField.vue_vue_type_script_setup_true_lang-D5xYofdb.js";
|
|
21
21
|
import { a as _t } from "./mediaQuery-CygcXmFW.js";
|
|
22
22
|
import { _ as xt } from "./Sheet.vue_vue_type_script_setup_true_lang-BG8HUNfs.js";
|
|
23
23
|
import { t as ke } from "./toast-CqSDTWRX.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { defineComponent as d, computed as u, useSlots as p, openBlock as w, createElementBlock as y, createVNode as f, unref as k, createSlots as b, renderList as m, withCtx as h, renderSlot as v, normalizeProps as _, guardReactiveProps as g } from "vue";
|
|
2
|
-
import { u as R, _ as L } from "./rowLayout-
|
|
2
|
+
import { u as R, _ as L } from "./rowLayout-PIuD7MGo.js";
|
|
3
3
|
const F = ["aria-busy"], V = /* @__PURE__ */ d({
|
|
4
4
|
__name: "DataTable",
|
|
5
5
|
props: {
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { computed as p, defineComponent as re, useModel as oe, useTemplateRef as T, openBlock as g, createBlock as Y, mergeProps as E, unref as s, createSlots as ae, withCtx as y, createElementBlock as C, Fragment as H, createVNode as D, createTextVNode as ne, toDisplayString as K, createCommentVNode as M, createElementVNode as O, normalizeClass as le, renderSlot as S, mergeModels as G, mergeDefaults as se, nextTick as J } from "vue";
|
|
2
2
|
import { useI18n as L } from "vue-i18n";
|
|
3
3
|
import { _ as ie } from "./DateButton.vue_vue_type_script_setup_true_lang-CovKG5lN.js";
|
|
4
|
-
import { u as W } from "./format-
|
|
4
|
+
import { u as W } from "./format-C_HXlOYQ.js";
|
|
5
5
|
import { _ as de } from "./Icon.vue_vue_type_script_lang-BhhsFYwp.js";
|
|
6
6
|
import { u as ue } from "./mediaQuery-CygcXmFW.js";
|
|
7
7
|
import { _ as ce } from "./Popover.vue_vue_type_script_setup_true_lang-BK8HL_V0.js";
|
|
8
|
-
import {
|
|
9
|
-
import { e as q, f as j, m as X, g as Z, h as
|
|
8
|
+
import { u as me, _ as fe } from "./options-mOOX6JSS.js";
|
|
9
|
+
import { e as q, f as j, m as X, g as Z, h as pe, j as be, u as ve, k as ye, _ as ke, l as ge, c as he } from "./useTypedEntry-BsMV66Yc.js";
|
|
10
|
+
import { f as xe, b as we } from "./FormRow.vue_vue_type_script_setup_true_lang-CpgNVQF4.js";
|
|
10
11
|
const _e = ["d", "m", "y"];
|
|
11
12
|
function $e(o) {
|
|
12
13
|
const r = o("2033-11-22"), t = { y: r.indexOf("2033") >= 0 ? r.indexOf("2033") : r.indexOf("33"), m: r.indexOf("11"), d: r.indexOf("22") };
|
|
@@ -53,7 +54,7 @@ function Te(o, r) {
|
|
|
53
54
|
function F(o, r) {
|
|
54
55
|
return Object.fromEntries(o.map((t, e) => [t, r[e]]));
|
|
55
56
|
}
|
|
56
|
-
function
|
|
57
|
+
function Ye(o) {
|
|
57
58
|
const r = o.trim().replace(/^(\d{4}-\d{2}-\d{2})T/, "$1 ").split(/\s+/).filter(Boolean), t = r[r.length - 1];
|
|
58
59
|
if (t === void 0) return { date: null, time: null };
|
|
59
60
|
if (!(t.includes(":") || r.length > 1 && /^\d{1,2}\.\d{2}$/.test(t))) return { date: r.join(" "), time: null };
|
|
@@ -83,8 +84,8 @@ function qe(o, r, t) {
|
|
|
83
84
|
const { t: e } = L();
|
|
84
85
|
return p(() => {
|
|
85
86
|
const a = q();
|
|
86
|
-
return (o() ??
|
|
87
|
-
const i =
|
|
87
|
+
return (o() ?? pe(r())).map((u) => {
|
|
88
|
+
const i = be(u, (n) => e(`core.form.date.${n.replace(/-/g, "_")}`), a);
|
|
88
89
|
return { ...i, disabled: Z(i.value, t()) };
|
|
89
90
|
});
|
|
90
91
|
});
|
|
@@ -92,7 +93,7 @@ function qe(o, r, t) {
|
|
|
92
93
|
const Pe = ["id", "name", "value", "placeholder", "disabled", "required", "aria-required", "aria-invalid", "aria-describedby"], Ve = ["aria-label", "onClick"], Be = { class: "flex flex-col gap-2.5" }, Ee = {
|
|
93
94
|
key: 0,
|
|
94
95
|
class: "border-t border-border-separator pt-2.5"
|
|
95
|
-
}, Me = { class: "text-footnote text-content-muted" },
|
|
96
|
+
}, Me = { class: "text-footnote text-content-muted" }, He = /* @__PURE__ */ re({
|
|
96
97
|
__name: "DateField",
|
|
97
98
|
props: /* @__PURE__ */ G(/* @__PURE__ */ se({
|
|
98
99
|
label: {},
|
|
@@ -110,20 +111,20 @@ const Pe = ["id", "name", "value", "placeholder", "disabled", "required", "aria-
|
|
|
110
111
|
disabledDates: { type: [Array, Function] },
|
|
111
112
|
openOn: {},
|
|
112
113
|
quickPicks: {}
|
|
113
|
-
}, { ...
|
|
114
|
+
}, { ...we, min: void 0, max: void 0, disabledDates: void 0, openOn: void 0, quickPicks: void 0 }), {
|
|
114
115
|
modelValue: { default: null },
|
|
115
116
|
modelModifiers: {}
|
|
116
117
|
}),
|
|
117
118
|
emits: /* @__PURE__ */ G(["focus", "blur"], ["update:modelValue"]),
|
|
118
119
|
setup(o, { expose: r, emit: t }) {
|
|
119
|
-
const e = o, a = oe(o, "modelValue"), u = t, { t: i } = L(), n = W(), x = ue(), c = T("input"), m = T("popover"), w = T("calendar"), N = T("sheet"), k = p(() => ({ min: e.min, max: e.max, disabled: e.disabledDates })), b = Oe(() => k.value), f =
|
|
120
|
+
const e = o, a = oe(o, "modelValue"), u = t, { t: i } = L(), n = W(), x = ue(), c = T("input"), m = T("popover"), w = T("calendar"), N = T("sheet"), k = p(() => ({ min: e.min, max: e.max, disabled: e.disabledDates })), b = Oe(() => k.value), f = ve({
|
|
120
121
|
model: a,
|
|
121
122
|
display: (l) => n.date(l),
|
|
122
123
|
parse: (l) => {
|
|
123
124
|
const d = b.parse(l);
|
|
124
125
|
return d ? b.available(d) ? { value: d } : { error: b.unavailableMessage() } : { error: b.invalidMessage() };
|
|
125
126
|
}
|
|
126
|
-
}), P = qe(() => e.quickPicks, () => x.value, () => k.value), z = p(() => e.error || f.message.value), V = p(() => a.value ? n.date(a.value) : null), ee = me("date", () => z.value ? "error" : e.disabled ? "locked" : "rest"), U = p(() => f.typed.value ?? (
|
|
127
|
+
}), P = qe(() => e.quickPicks, () => x.value, () => k.value), z = p(() => e.error || f.message.value), V = p(() => a.value ? n.date(a.value) : null), ee = me("date", () => z.value ? "error" : e.disabled ? "locked" : "rest"), U = p(() => f.typed.value ?? (ye(a.value) ? a.value : null));
|
|
127
128
|
async function B(l) {
|
|
128
129
|
e.disabled || (m.value?.present(), l && (await J(), await J(), w.value?.focus()));
|
|
129
130
|
}
|
|
@@ -133,7 +134,7 @@ const Pe = ["id", "name", "value", "placeholder", "disabled", "required", "aria-
|
|
|
133
134
|
function R(l, d) {
|
|
134
135
|
f.set(l), d();
|
|
135
136
|
}
|
|
136
|
-
return r({ focus: () => c.value?.focus() }), (l, d) => (g(), Y(fe, E({ ...s(
|
|
137
|
+
return r({ focus: () => c.value?.focus() }), (l, d) => (g(), Y(fe, E({ ...s(xe)(e), error: z.value }, {
|
|
137
138
|
value: V.value,
|
|
138
139
|
"value-style": "numeric"
|
|
139
140
|
}), ae({
|
|
@@ -152,7 +153,7 @@ const Pe = ["id", "name", "value", "placeholder", "disabled", "required", "aria-
|
|
|
152
153
|
]),
|
|
153
154
|
_: 1
|
|
154
155
|
}, 16, ["disabled", "invalid", "placeholder"]),
|
|
155
|
-
D(
|
|
156
|
+
D(ke, {
|
|
156
157
|
ref_key: "sheet",
|
|
157
158
|
ref: N,
|
|
158
159
|
title: e.label ?? s(i)("core.form.date.calendar"),
|
|
@@ -223,7 +224,7 @@ const Pe = ["id", "name", "value", "placeholder", "disabled", "required", "aria-
|
|
|
223
224
|
]),
|
|
224
225
|
default: y(({ dismiss: _ }) => [
|
|
225
226
|
O("div", Be, [
|
|
226
|
-
D(
|
|
227
|
+
D(ge, {
|
|
227
228
|
ref_key: "calendar",
|
|
228
229
|
ref: w,
|
|
229
230
|
"model-value": U.value,
|
|
@@ -235,7 +236,7 @@ const Pe = ["id", "name", "value", "placeholder", "disabled", "required", "aria-
|
|
|
235
236
|
"onUpdate:modelValue": ($) => R($, _)
|
|
236
237
|
}, null, 8, ["model-value", "min", "max", "disabled-dates", "open-on", "onUpdate:modelValue"]),
|
|
237
238
|
s(P).length > 0 ? (g(), C("div", Ee, [
|
|
238
|
-
D(
|
|
239
|
+
D(he, {
|
|
239
240
|
items: s(P),
|
|
240
241
|
selected: U.value,
|
|
241
242
|
onPick: ($) => R($, _)
|
|
@@ -274,8 +275,8 @@ const Pe = ["id", "name", "value", "placeholder", "disabled", "required", "aria-
|
|
|
274
275
|
}
|
|
275
276
|
});
|
|
276
277
|
export {
|
|
277
|
-
|
|
278
|
+
He as _,
|
|
278
279
|
qe as a,
|
|
279
|
-
|
|
280
|
+
Ye as s,
|
|
280
281
|
Oe as u
|
|
281
282
|
};
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { defineComponent as B, useTemplateRef as C, computed as y, ref as v, openBlock as D, createBlock as z, unref as r, withCtx as m, createVNode as F, createElementVNode as b, normalizeClass as $, toDisplayString as h } from "vue";
|
|
2
2
|
import { useI18n as q } from "vue-i18n";
|
|
3
3
|
import { a as k } from "./error-CD7x0Jrz.js";
|
|
4
|
-
import { u as V, _ as N } from "./CollectionPage.vue_vue_type_script_setup_true_lang-
|
|
4
|
+
import { u as V, _ as N } from "./CollectionPage.vue_vue_type_script_setup_true_lang-Dr6nFNBB.js";
|
|
5
5
|
import { u as P } from "./describeError-B-NMa--w.js";
|
|
6
|
-
import { u as I } from "./format-
|
|
7
|
-
import { e as a, R as O } from "./index-
|
|
6
|
+
import { u as I } from "./format-C_HXlOYQ.js";
|
|
7
|
+
import { e as a, R as O } from "./index-SLJWm40T.js";
|
|
8
8
|
import { _ as W } from "./AlertDialog.vue_vue_type_script_setup_true_lang-WuGvAOrj.js";
|
|
9
9
|
import { t as i } from "./toast-CqSDTWRX.js";
|
|
10
10
|
import { u as Y } from "./useLoad-M7V-AVwR.js";
|
|
11
|
-
import { u as j } from "./platform-
|
|
11
|
+
import { u as j } from "./platform-DU9QFts8.js";
|
|
12
12
|
import { d as G, r as H } from "./http-D6qOS6xs.js";
|
|
13
13
|
function J(u) {
|
|
14
14
|
return G({
|
|
@@ -4,11 +4,11 @@ var z = (o, e, t) => de(o, typeof e != "symbol" ? e + "" : e, t);
|
|
|
4
4
|
import { shallowRef as N, computed as v, toRaw as fe, reactive as me, ref as V, watch as pe, nextTick as ve, toValue as ge, defineComponent as J, unref as $, openBlock as g, createBlock as Q, withCtx as ne, createElementBlock as k, toDisplayString as j, createCommentVNode as y, Fragment as W, createElementVNode as R, normalizeClass as P, renderList as he, createTextVNode as D, inject as le, provide as H, useSlots as ye, shallowReactive as re, useTemplateRef as be, useId as ke, normalizeStyle as _e, renderSlot as I } from "vue";
|
|
5
5
|
import { useI18n as X } from "vue-i18n";
|
|
6
6
|
import { i as we, a as L } from "./error-CD7x0Jrz.js";
|
|
7
|
-
import { f as je } from "./serverMessages-
|
|
7
|
+
import { f as je } from "./serverMessages-C_KkDvpT.js";
|
|
8
8
|
import { d as Ee, u as Oe, a as xe } from "./describeError-B-NMa--w.js";
|
|
9
9
|
import { _ as $e } from "./Banner.vue_vue_type_script_setup_true_lang-sv0phngk.js";
|
|
10
10
|
import { s as Ae, u as Fe } from "./sectionIndex-BS0ic5W7.js";
|
|
11
|
-
import {
|
|
11
|
+
import { c as se, d as Be } from "./FormRow.vue_vue_type_script_setup_true_lang-CpgNVQF4.js";
|
|
12
12
|
import { _ as De } from "./Button.vue_vue_type_script_setup_true_lang-JrqhO99l.js";
|
|
13
13
|
class Se {
|
|
14
14
|
constructor() {
|