@jskit-ai/ui-generator 0.1.6 → 0.1.8
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/README.md
CHANGED
|
@@ -31,7 +31,7 @@ npx jskit generate @jskit-ai/ui-generator page --name "Reports" --surface admin
|
|
|
31
31
|
Generate an element at a specific outlet:
|
|
32
32
|
|
|
33
33
|
```bash
|
|
34
|
-
npx jskit generate @jskit-ai/ui-generator element --name "Ops Panel" --surface admin --placement
|
|
34
|
+
npx jskit generate @jskit-ai/ui-generator element --name "Ops Panel" --surface admin --placement admin-settings:forms
|
|
35
35
|
```
|
|
36
36
|
|
|
37
37
|
Generate an element with custom component path:
|
package/package.descriptor.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export default Object.freeze({
|
|
2
2
|
packageVersion: 1,
|
|
3
3
|
packageId: "@jskit-ai/ui-generator",
|
|
4
|
-
version: "0.1.
|
|
4
|
+
version: "0.1.8",
|
|
5
5
|
kind: "generator",
|
|
6
6
|
description: "Generate app-local non-CRUD UI pages and outlet elements.",
|
|
7
7
|
options: {
|
|
@@ -149,7 +149,7 @@ export default Object.freeze({
|
|
|
149
149
|
mutations: {
|
|
150
150
|
dependencies: {
|
|
151
151
|
runtime: {
|
|
152
|
-
"@jskit-ai/users-web": "0.1.
|
|
152
|
+
"@jskit-ai/users-web": "0.1.40"
|
|
153
153
|
},
|
|
154
154
|
dev: {}
|
|
155
155
|
},
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jskit-ai/ui-generator",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.8",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "node --test"
|
|
7
7
|
},
|
|
8
8
|
"dependencies": {
|
|
9
|
-
"@jskit-ai/kernel": "0.1.
|
|
9
|
+
"@jskit-ai/kernel": "0.1.25"
|
|
10
10
|
},
|
|
11
11
|
"exports": {
|
|
12
12
|
"./server/buildTemplateContext": "./src/server/buildTemplateContext.js"
|
|
@@ -331,7 +331,10 @@ function renderTabLinkItemSource() {
|
|
|
331
331
|
import { computed } from "vue";
|
|
332
332
|
import { useRoute } from "vue-router";
|
|
333
333
|
import { usePaths } from "@jskit-ai/users-web/client/composables/usePaths";
|
|
334
|
-
import {
|
|
334
|
+
import {
|
|
335
|
+
normalizeMenuLinkPathname,
|
|
336
|
+
resolveMenuLinkTarget
|
|
337
|
+
} from "@jskit-ai/users-web/client/support/menuLinkTarget";
|
|
335
338
|
|
|
336
339
|
const props = defineProps({
|
|
337
340
|
label: {
|
|
@@ -362,78 +365,25 @@ const props = defineProps({
|
|
|
362
365
|
|
|
363
366
|
const route = useRoute();
|
|
364
367
|
const paths = usePaths();
|
|
365
|
-
const { currentSurfaceId, workspaceSlugFromRoute } = useWorkspaceRouteContext();
|
|
366
|
-
|
|
367
|
-
function normalizePathname(pathname = "") {
|
|
368
|
-
const source = String(pathname || "").trim();
|
|
369
|
-
if (!source) {
|
|
370
|
-
return "";
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
const queryIndex = source.indexOf("?");
|
|
374
|
-
const hashIndex = source.indexOf("#");
|
|
375
|
-
const cutoff =
|
|
376
|
-
queryIndex < 0
|
|
377
|
-
? hashIndex
|
|
378
|
-
: hashIndex < 0
|
|
379
|
-
? queryIndex
|
|
380
|
-
: Math.min(queryIndex, hashIndex);
|
|
381
|
-
return cutoff < 0 ? source : source.slice(0, cutoff);
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
function interpolateBracketParams(pathTemplate = "", params = {}) {
|
|
385
|
-
const source = String(pathTemplate || "").trim();
|
|
386
|
-
if (!source) {
|
|
387
|
-
return "";
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
return source.replace(/\\[([^\\]]+)\\]/g, (_match, rawKey) => {
|
|
391
|
-
const key = String(rawKey || "").trim();
|
|
392
|
-
if (!key) {
|
|
393
|
-
return "";
|
|
394
|
-
}
|
|
395
|
-
const value = params?.[key];
|
|
396
|
-
return value == null ? "[" + key + "]" : encodeURIComponent(String(value));
|
|
397
|
-
});
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
const targetSurfaceId = computed(() => {
|
|
401
|
-
const explicitSurface = String(props.surface || "").trim().toLowerCase();
|
|
402
|
-
if (explicitSurface && explicitSurface !== "*") {
|
|
403
|
-
return explicitSurface;
|
|
404
|
-
}
|
|
405
|
-
return String(currentSurfaceId.value || paths.currentSurfaceId.value || "").trim().toLowerCase();
|
|
406
|
-
});
|
|
407
368
|
|
|
408
369
|
const resolvedTo = computed(() => {
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
});
|
|
420
|
-
}
|
|
370
|
+
return resolveMenuLinkTarget({
|
|
371
|
+
to: props.to,
|
|
372
|
+
surface: props.surface,
|
|
373
|
+
currentSurfaceId: paths.currentSurfaceId.value,
|
|
374
|
+
placementContext: paths.placementContext.value,
|
|
375
|
+
workspaceSuffix: props.workspaceSuffix,
|
|
376
|
+
nonWorkspaceSuffix: props.nonWorkspaceSuffix,
|
|
377
|
+
routeParams: route.params || {},
|
|
378
|
+
resolvePagePath(relativePath, options = {}) {
|
|
379
|
+
return paths.page(relativePath, options);
|
|
421
380
|
}
|
|
422
|
-
return explicitTo;
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
const workspaceSlug = String(workspaceSlugFromRoute.value || "").trim();
|
|
426
|
-
const suffix = workspaceSlug ? props.workspaceSuffix : props.nonWorkspaceSuffix;
|
|
427
|
-
const normalizedSuffix = String(suffix || "/").trim() || "/";
|
|
428
|
-
return paths.page(normalizedSuffix, {
|
|
429
|
-
surface: targetSurfaceId.value,
|
|
430
|
-
mode: "auto"
|
|
431
381
|
});
|
|
432
382
|
});
|
|
433
383
|
|
|
434
384
|
const isActive = computed(() => {
|
|
435
|
-
const targetPathname =
|
|
436
|
-
const currentPathname =
|
|
385
|
+
const targetPathname = normalizeMenuLinkPathname(resolvedTo.value);
|
|
386
|
+
const currentPathname = normalizeMenuLinkPathname(route.fullPath || route.path);
|
|
437
387
|
if (!targetPathname || !currentPathname) {
|
|
438
388
|
return false;
|
|
439
389
|
}
|
|
@@ -49,7 +49,7 @@ test("buildUiPageTemplateContext resolves placement from default app ShellOutlet
|
|
|
49
49
|
"src/pages/admin/workspace/settings/index.vue",
|
|
50
50
|
`<template>
|
|
51
51
|
<section>
|
|
52
|
-
<ShellOutlet host="
|
|
52
|
+
<ShellOutlet host="admin-settings" position="forms" default />
|
|
53
53
|
</section>
|
|
54
54
|
</template>
|
|
55
55
|
`
|
|
@@ -59,7 +59,7 @@ test("buildUiPageTemplateContext resolves placement from default app ShellOutlet
|
|
|
59
59
|
appRoot,
|
|
60
60
|
options: {}
|
|
61
61
|
});
|
|
62
|
-
assert.equal(context.__JSKIT_UI_MENU_PLACEMENT_HOST__, "
|
|
62
|
+
assert.equal(context.__JSKIT_UI_MENU_PLACEMENT_HOST__, "admin-settings");
|
|
63
63
|
assert.equal(context.__JSKIT_UI_MENU_PLACEMENT_POSITION__, "forms");
|
|
64
64
|
assert.equal(context.__JSKIT_UI_MENU_COMPONENT_TOKEN__, "users.web.shell.surface-aware-menu-link-item");
|
|
65
65
|
assert.equal(context.__JSKIT_UI_MENU_WORKSPACE_SUFFIX__, "/");
|
|
@@ -115,10 +115,10 @@ test("ui-generator container subcommand creates parent route container with Shel
|
|
|
115
115
|
assert.match(sectionShellSource, /<ShellOutlet :host="props\.host" :position="props\.position" \/>/);
|
|
116
116
|
|
|
117
117
|
const tabLinkSource = await readFile(path.join(appRoot, "src", "components", "TabLinkItem.vue"), "utf8");
|
|
118
|
-
assert.match(tabLinkSource, /
|
|
118
|
+
assert.match(tabLinkSource, /@jskit-ai\/users-web\/client\/support\/menuLinkTarget/);
|
|
119
|
+
assert.match(tabLinkSource, /resolveMenuLinkTarget/);
|
|
120
|
+
assert.match(tabLinkSource, /normalizeMenuLinkPathname/);
|
|
119
121
|
assert.match(tabLinkSource, /class="tab-link-item text-none"/);
|
|
120
|
-
assert.equal(tabLinkSource.includes("source.replace(/\\[([^\\]]+)\\]/g"), true);
|
|
121
|
-
assert.equal(tabLinkSource.includes("source.replace(/[([^]]+)]/g"), false);
|
|
122
122
|
|
|
123
123
|
const providerSource = await readFile(
|
|
124
124
|
path.join(appRoot, "packages", "main", "src", "client", "providers", "MainClientProvider.js"),
|
|
@@ -34,7 +34,7 @@ async function writeAppFixture(appRoot) {
|
|
|
34
34
|
path.join(appRoot, "src", "pages", "admin", "workspace", "settings", "index.vue"),
|
|
35
35
|
`<template>
|
|
36
36
|
<section>
|
|
37
|
-
<ShellOutlet host="
|
|
37
|
+
<ShellOutlet host="admin-settings" position="forms" />
|
|
38
38
|
</section>
|
|
39
39
|
</template>
|
|
40
40
|
`,
|
|
@@ -86,7 +86,7 @@ test("ui-generator element subcommand creates component and outlet placement", a
|
|
|
86
86
|
options: {
|
|
87
87
|
name: "Ops Panel",
|
|
88
88
|
surface: "admin",
|
|
89
|
-
placement: "
|
|
89
|
+
placement: "admin-settings:forms"
|
|
90
90
|
}
|
|
91
91
|
});
|
|
92
92
|
|
|
@@ -105,7 +105,7 @@ test("ui-generator element subcommand creates component and outlet placement", a
|
|
|
105
105
|
|
|
106
106
|
const placementSource = await readFile(path.join(appRoot, "src", "placement.js"), "utf8");
|
|
107
107
|
assert.match(placementSource, /id: "ui-generator\.element\.ops-panel"/);
|
|
108
|
-
assert.match(placementSource, /host: "
|
|
108
|
+
assert.match(placementSource, /host: "admin-settings"/);
|
|
109
109
|
assert.match(placementSource, /position: "forms"/);
|
|
110
110
|
assert.match(placementSource, /componentToken: "local\.main\.ui\.element\.ops-panel"/);
|
|
111
111
|
});
|