@forwardimpact/pathway 0.22.0 → 0.23.1
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/bin/fit-pathway.js +8 -4
- package/package.json +6 -2
- package/src/commands/agent.js +6 -3
- package/src/commands/behaviour.js +11 -1
- package/src/commands/build.js +11 -2
- package/src/commands/command-factory.js +4 -2
- package/src/commands/dev.js +9 -2
- package/src/commands/discipline.js +25 -10
- package/src/commands/driver.js +11 -1
- package/src/commands/job.js +127 -28
- package/src/commands/level.js +25 -3
- package/src/commands/skill.js +11 -1
- package/src/commands/stage.js +11 -1
- package/src/commands/tool.js +6 -3
- package/src/commands/track.js +20 -4
- package/src/components/card.js +8 -104
- package/src/components/comparison-radar.js +1 -1
- package/src/components/detail.js +16 -118
- package/src/components/error-page.js +8 -68
- package/src/components/grid.js +12 -106
- package/src/components/list.js +7 -116
- package/src/components/nav.js +7 -60
- package/src/css/bundles/app.css +25 -21
- package/src/css/bundles/handout.css +33 -33
- package/src/css/bundles/slides.css +25 -25
- package/src/formatters/discipline/markdown.js +16 -1
- package/src/formatters/interview/shared.js +3 -3
- package/src/formatters/job/description.js +2 -2
- package/src/formatters/progress/shared.js +3 -3
- package/src/formatters/skill/shared.js +1 -1
- package/src/formatters/track/markdown.js +14 -0
- package/src/formatters/track/shared.js +1 -1
- package/src/handout.html +32 -13
- package/src/index.html +32 -13
- package/src/lib/error-boundary.js +3 -66
- package/src/lib/errors.js +7 -45
- package/src/lib/job-cache.js +1 -1
- package/src/lib/markdown.js +2 -109
- package/src/lib/reactive.js +7 -73
- package/src/lib/render.js +49 -197
- package/src/lib/router-core.js +2 -156
- package/src/lib/router-pages.js +2 -11
- package/src/lib/router-slides.js +2 -197
- package/src/lib/state.js +14 -63
- package/src/lib/utils.js +3 -10
- package/src/lib/yaml-loader.js +13 -71
- package/src/pages/agent-builder.js +1 -1
- package/src/pages/assessment-results.js +1 -1
- package/src/pages/job-builder.js +1 -1
- package/src/pages/job.js +1 -1
- package/src/pages/skill.js +1 -1
- package/src/slide-main.js +1 -1
- package/src/slides/index.js +1 -1
- package/src/slides/job.js +1 -1
- package/src/slides/overview.js +1 -1
- package/src/slides.html +32 -13
- package/src/css/base.css +0 -56
- package/src/css/components/badges.css +0 -232
- package/src/css/components/buttons.css +0 -101
- package/src/css/components/forms.css +0 -191
- package/src/css/components/layout.css +0 -218
- package/src/css/components/nav.css +0 -206
- package/src/css/components/progress.css +0 -166
- package/src/css/components/states.css +0 -82
- package/src/css/components/surfaces.css +0 -347
- package/src/css/components/tables.css +0 -362
- package/src/css/components/top-bar.css +0 -180
- package/src/css/components/typography.css +0 -121
- package/src/css/components/utilities.css +0 -41
- package/src/css/pages/detail.css +0 -119
- package/src/css/reset.css +0 -50
- package/src/css/tokens.css +0 -162
- package/src/css/views/handout.css +0 -30
- package/src/css/views/print.css +0 -634
- package/src/css/views/slide-animations.css +0 -113
- package/src/css/views/slide-base.css +0 -331
- package/src/css/views/slide-sections.css +0 -597
- package/src/css/views/slide-tables.css +0 -275
package/src/commands/tool.js
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* npx pathway tool <name> # Detail view for specific tool
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
+
import { truncate } from "../formatters/shared.js";
|
|
12
13
|
import { prepareToolsList } from "../formatters/tool/shared.js";
|
|
13
14
|
import {
|
|
14
15
|
formatTable,
|
|
@@ -27,10 +28,10 @@ export async function runToolCommand({ data, args, options }) {
|
|
|
27
28
|
const [name] = args;
|
|
28
29
|
const { tools, totalCount } = prepareToolsList(data.skills);
|
|
29
30
|
|
|
30
|
-
// --list: Output
|
|
31
|
+
// --list: Output descriptive comma-separated tool lines for piping
|
|
31
32
|
if (options.list) {
|
|
32
33
|
for (const tool of tools) {
|
|
33
|
-
console.log(tool.name);
|
|
34
|
+
console.log(`${tool.name}, ${truncate(tool.description, 60)}`);
|
|
34
35
|
}
|
|
35
36
|
return;
|
|
36
37
|
}
|
|
@@ -87,7 +88,9 @@ function formatSummary(tools, totalCount) {
|
|
|
87
88
|
if (sorted.length > 15) {
|
|
88
89
|
console.log(`(showing top 15 by usage)`);
|
|
89
90
|
}
|
|
90
|
-
console.log(
|
|
91
|
+
console.log(
|
|
92
|
+
`\nRun 'npx pathway tool --list' for all tool names and descriptions`,
|
|
93
|
+
);
|
|
91
94
|
console.log(`Run 'npx pathway tool <name>' for details\n`);
|
|
92
95
|
}
|
|
93
96
|
|
package/src/commands/track.js
CHANGED
|
@@ -16,25 +16,40 @@ import { sortTracksByName } from "../formatters/track/shared.js";
|
|
|
16
16
|
import { formatTable } from "../lib/cli-output.js";
|
|
17
17
|
import { getConceptEmoji } from "@forwardimpact/map/levels";
|
|
18
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Format track list item for --list output
|
|
21
|
+
* @param {Object} track - Track entity
|
|
22
|
+
* @returns {string} Formatted list line
|
|
23
|
+
*/
|
|
24
|
+
function formatListItem(track) {
|
|
25
|
+
return `${track.id}, ${track.name}`;
|
|
26
|
+
}
|
|
27
|
+
|
|
19
28
|
/**
|
|
20
29
|
* Format track summary output
|
|
21
30
|
* @param {Array} tracks - Raw track entities
|
|
22
31
|
* @param {Object} data - Full data context
|
|
23
32
|
*/
|
|
24
33
|
function formatSummary(tracks, data) {
|
|
25
|
-
const { framework } = data;
|
|
34
|
+
const { framework, disciplines } = data;
|
|
26
35
|
const emoji = framework ? getConceptEmoji(framework, "track") : "🛤️";
|
|
27
36
|
|
|
28
37
|
console.log(`\n${emoji} Tracks\n`);
|
|
29
38
|
|
|
30
39
|
const rows = tracks.map((t) => {
|
|
31
40
|
const modCount = Object.keys(t.skillModifiers || {}).length;
|
|
32
|
-
|
|
41
|
+
const usedBy = disciplines
|
|
42
|
+
? disciplines.filter((d) => d.validTracks && d.validTracks.includes(t.id))
|
|
43
|
+
: [];
|
|
44
|
+
const disciplineNames = usedBy
|
|
45
|
+
.map((d) => d.specialization || d.id)
|
|
46
|
+
.join(", ");
|
|
47
|
+
return [t.id, t.name, modCount, disciplineNames || "—"];
|
|
33
48
|
});
|
|
34
49
|
|
|
35
|
-
console.log(formatTable(["ID", "Name", "Modifiers"], rows));
|
|
50
|
+
console.log(formatTable(["ID", "Name", "Modifiers", "Disciplines"], rows));
|
|
36
51
|
console.log(`\nTotal: ${tracks.length} tracks`);
|
|
37
|
-
console.log(`\nRun 'npx pathway track --list' for IDs`);
|
|
52
|
+
console.log(`\nRun 'npx pathway track --list' for IDs and names`);
|
|
38
53
|
console.log(`Run 'npx pathway track <id>' for details\n`);
|
|
39
54
|
}
|
|
40
55
|
|
|
@@ -63,5 +78,6 @@ export const runTrackCommand = createEntityCommand({
|
|
|
63
78
|
sortItems: sortTracksByName,
|
|
64
79
|
formatSummary,
|
|
65
80
|
formatDetail,
|
|
81
|
+
formatListItem,
|
|
66
82
|
emojiIcon: "🛤️",
|
|
67
83
|
});
|
package/src/components/card.js
CHANGED
|
@@ -1,108 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Reusable card component
|
|
3
|
+
*
|
|
4
|
+
* Re-exports from @forwardimpact/libui/components/card.
|
|
3
5
|
*/
|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
* @param {string} [options.description] - Card description
|
|
12
|
-
* @param {string} [options.href] - Link destination (makes card clickable)
|
|
13
|
-
* @param {HTMLElement[]} [options.badges] - Badges to display
|
|
14
|
-
* @param {HTMLElement[]} [options.meta] - Meta information
|
|
15
|
-
* @param {HTMLElement} [options.content] - Additional content
|
|
16
|
-
* @param {HTMLElement} [options.icon] - Icon element to display
|
|
17
|
-
* @param {string} [options.className] - Additional CSS class
|
|
18
|
-
* @returns {HTMLElement}
|
|
19
|
-
*/
|
|
20
|
-
export function createCard({
|
|
21
|
-
title,
|
|
22
|
-
description,
|
|
23
|
-
href,
|
|
24
|
-
badges = [],
|
|
25
|
-
meta = [],
|
|
26
|
-
content,
|
|
27
|
-
icon,
|
|
28
|
-
className = "",
|
|
29
|
-
}) {
|
|
30
|
-
const isClickable = !!href;
|
|
31
|
-
|
|
32
|
-
const titleContent = icon
|
|
33
|
-
? div(
|
|
34
|
-
{ className: "card-title-with-icon" },
|
|
35
|
-
icon,
|
|
36
|
-
h3({ className: "card-title" }, title),
|
|
37
|
-
)
|
|
38
|
-
: h3({ className: "card-title" }, title);
|
|
39
|
-
|
|
40
|
-
const cardHeader = div(
|
|
41
|
-
{ className: "card-header" },
|
|
42
|
-
titleContent,
|
|
43
|
-
badges.length > 0 ? div({ className: "card-badges" }, ...badges) : null,
|
|
44
|
-
);
|
|
45
|
-
|
|
46
|
-
const card = div(
|
|
47
|
-
{
|
|
48
|
-
className:
|
|
49
|
-
`card ${isClickable ? "card-clickable" : ""} ${className}`.trim(),
|
|
50
|
-
},
|
|
51
|
-
cardHeader,
|
|
52
|
-
description ? p({ className: "card-description" }, description) : null,
|
|
53
|
-
content || null,
|
|
54
|
-
meta.length > 0 ? div({ className: "card-meta" }, ...meta) : null,
|
|
55
|
-
);
|
|
56
|
-
|
|
57
|
-
if (isClickable) {
|
|
58
|
-
card.addEventListener("click", () => {
|
|
59
|
-
window.location.hash = href;
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
return card;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Create a stat card for the landing page
|
|
68
|
-
* @param {Object} options
|
|
69
|
-
* @param {number|string} options.value - The stat value
|
|
70
|
-
* @param {string} options.label - The stat label
|
|
71
|
-
* @param {string} [options.href] - Optional link
|
|
72
|
-
* @returns {HTMLElement}
|
|
73
|
-
*/
|
|
74
|
-
export function createStatCard({ value, label, href }) {
|
|
75
|
-
const card = div(
|
|
76
|
-
{ className: "stat-card" },
|
|
77
|
-
div({ className: "stat-value" }, String(value)),
|
|
78
|
-
div({ className: "stat-label" }, label),
|
|
79
|
-
);
|
|
80
|
-
|
|
81
|
-
if (href) {
|
|
82
|
-
card.style.cursor = "pointer";
|
|
83
|
-
card.addEventListener("click", () => {
|
|
84
|
-
window.location.hash = href;
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
return card;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Create a badge element
|
|
93
|
-
* @param {string} text - Badge text
|
|
94
|
-
* @param {string} [type] - Badge type (default, primary, secondary, broad, technical, ai, etc.)
|
|
95
|
-
* @returns {HTMLElement}
|
|
96
|
-
*/
|
|
97
|
-
export function createBadge(text, type = "default") {
|
|
98
|
-
return span({ className: `badge badge-${type}` }, text);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* Create a tag element
|
|
103
|
-
* @param {string} text
|
|
104
|
-
* @returns {HTMLElement}
|
|
105
|
-
*/
|
|
106
|
-
export function createTag(text) {
|
|
107
|
-
return span({ className: "info-tag" }, text);
|
|
108
|
-
}
|
|
7
|
+
export {
|
|
8
|
+
createCard,
|
|
9
|
+
createStatCard,
|
|
10
|
+
createBadge,
|
|
11
|
+
createTag,
|
|
12
|
+
} from "@forwardimpact/libui/components/card";
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
getBehaviourMaturityIndex,
|
|
14
14
|
formatLevel,
|
|
15
15
|
} from "../lib/render.js";
|
|
16
|
-
import { compareByCapability } from "@forwardimpact/
|
|
16
|
+
import { compareByCapability } from "@forwardimpact/libskill/policies";
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
19
|
* Create a comparison skill radar chart
|
package/src/components/detail.js
CHANGED
|
@@ -1,13 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Detail view components
|
|
3
|
+
*
|
|
4
|
+
* Re-exports generic components from @forwardimpact/libui/components/detail
|
|
5
|
+
* and provides domain-specific level display components.
|
|
3
6
|
*/
|
|
4
7
|
|
|
8
|
+
export {
|
|
9
|
+
createDetailHeader,
|
|
10
|
+
createDetailSection,
|
|
11
|
+
createLinksList,
|
|
12
|
+
createTagsList,
|
|
13
|
+
createDetailItem,
|
|
14
|
+
} from "@forwardimpact/libui/components/detail";
|
|
15
|
+
|
|
5
16
|
import {
|
|
6
17
|
div,
|
|
7
|
-
h1,
|
|
8
|
-
h2,
|
|
9
|
-
p,
|
|
10
|
-
a,
|
|
11
18
|
span,
|
|
12
19
|
table,
|
|
13
20
|
thead,
|
|
@@ -15,63 +22,13 @@ import {
|
|
|
15
22
|
tr,
|
|
16
23
|
th,
|
|
17
24
|
td,
|
|
18
|
-
|
|
19
|
-
} from "
|
|
20
|
-
import { createBackLink } from "./nav.js";
|
|
21
|
-
import { createTag } from "./card.js";
|
|
22
|
-
import { formatLevel } from "../lib/render.js";
|
|
25
|
+
formatLevel,
|
|
26
|
+
} from "@forwardimpact/libui/render";
|
|
23
27
|
import {
|
|
24
28
|
SKILL_PROFICIENCY_ORDER,
|
|
25
29
|
BEHAVIOUR_MATURITY_ORDER,
|
|
26
30
|
} from "@forwardimpact/map/levels";
|
|
27
31
|
|
|
28
|
-
/**
|
|
29
|
-
* Create a detail page header
|
|
30
|
-
* @param {Object} options
|
|
31
|
-
* @param {string} options.title
|
|
32
|
-
* @param {string} [options.description]
|
|
33
|
-
* @param {string} options.backLink - Path to go back to
|
|
34
|
-
* @param {string} [options.backText] - Back link text
|
|
35
|
-
* @param {HTMLElement[]} [options.badges]
|
|
36
|
-
* @param {HTMLElement[]} [options.actions] - Action buttons
|
|
37
|
-
* @returns {HTMLElement}
|
|
38
|
-
*/
|
|
39
|
-
export function createDetailHeader({
|
|
40
|
-
title,
|
|
41
|
-
description,
|
|
42
|
-
backLink,
|
|
43
|
-
backText = "← Back to list",
|
|
44
|
-
badges = [],
|
|
45
|
-
actions = [],
|
|
46
|
-
}) {
|
|
47
|
-
return div(
|
|
48
|
-
{ className: "page-header" },
|
|
49
|
-
createBackLink(backLink, backText),
|
|
50
|
-
div(
|
|
51
|
-
{ className: "card-header" },
|
|
52
|
-
h1({ className: "page-title" }, title),
|
|
53
|
-
badges.length > 0 ? div({ className: "page-meta" }, ...badges) : null,
|
|
54
|
-
),
|
|
55
|
-
description ? p({ className: "page-description" }, description) : null,
|
|
56
|
-
actions.length > 0 ? div({ className: "page-actions" }, ...actions) : null,
|
|
57
|
-
);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Create a detail section
|
|
62
|
-
* @param {Object} options
|
|
63
|
-
* @param {string} options.title
|
|
64
|
-
* @param {HTMLElement} options.content
|
|
65
|
-
* @returns {HTMLElement}
|
|
66
|
-
*/
|
|
67
|
-
export function createDetailSection({ title, content }) {
|
|
68
|
-
return section(
|
|
69
|
-
{ className: "section section-detail" },
|
|
70
|
-
h2({ className: "section-title" }, title),
|
|
71
|
-
content,
|
|
72
|
-
);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
32
|
/**
|
|
76
33
|
* Create a level descriptions table
|
|
77
34
|
* @param {Object} descriptions - Level descriptions object
|
|
@@ -89,7 +46,7 @@ export function createLevelTable(descriptions, type = "skill") {
|
|
|
89
46
|
const maxLevels = levels.length;
|
|
90
47
|
|
|
91
48
|
const rows = levels.map((level) => {
|
|
92
|
-
const description = descriptions?.[level] || "
|
|
49
|
+
const description = descriptions?.[level] || "\u2014";
|
|
93
50
|
const levelIndex = parseInt(levelLabels[level]);
|
|
94
51
|
return tr(
|
|
95
52
|
{},
|
|
@@ -147,66 +104,7 @@ export function createLevelCell(levelIndex, maxLevels, levelName) {
|
|
|
147
104
|
export function createEmptyLevelCell() {
|
|
148
105
|
return td(
|
|
149
106
|
{ className: "level-cell" },
|
|
150
|
-
span({ className: "level-label text-muted" }, "
|
|
151
|
-
);
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* Create a links list
|
|
156
|
-
* @param {Array<{id: string, name: string}>} items
|
|
157
|
-
* @param {string} basePath - Base path for links (e.g., '/skill')
|
|
158
|
-
* @param {string} [emptyMessage='None']
|
|
159
|
-
* @param {Function} [getDisplayName] - Optional function to get display name
|
|
160
|
-
* @returns {HTMLElement}
|
|
161
|
-
*/
|
|
162
|
-
export function createLinksList(
|
|
163
|
-
items,
|
|
164
|
-
basePath,
|
|
165
|
-
emptyMessage = "None",
|
|
166
|
-
getDisplayName,
|
|
167
|
-
) {
|
|
168
|
-
if (!items || items.length === 0) {
|
|
169
|
-
return p({ className: "text-muted" }, emptyMessage);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
const displayFn = getDisplayName || ((item) => item.name);
|
|
173
|
-
const links = items.map((item) =>
|
|
174
|
-
a({ href: `#${basePath}/${item.id}` }, displayFn(item)),
|
|
175
|
-
);
|
|
176
|
-
|
|
177
|
-
return div({ className: "links-list" }, ...links);
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
/**
|
|
181
|
-
* Create a tags list
|
|
182
|
-
* @param {string[]} tags
|
|
183
|
-
* @param {string} [emptyMessage='None']
|
|
184
|
-
* @returns {HTMLElement}
|
|
185
|
-
*/
|
|
186
|
-
export function createTagsList(tags, emptyMessage = "None") {
|
|
187
|
-
if (!tags || tags.length === 0) {
|
|
188
|
-
return p({ className: "text-muted" }, emptyMessage);
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
return div({ className: "info-tags" }, ...tags.map((tag) => createTag(tag)));
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
/**
|
|
195
|
-
* Create a detail grid item
|
|
196
|
-
* @param {string} label
|
|
197
|
-
* @param {string|HTMLElement} value
|
|
198
|
-
* @returns {HTMLElement}
|
|
199
|
-
*/
|
|
200
|
-
export function createDetailItem(label, value) {
|
|
201
|
-
const valueEl =
|
|
202
|
-
typeof value === "string"
|
|
203
|
-
? div({ className: "detail-item-value" }, value)
|
|
204
|
-
: value;
|
|
205
|
-
|
|
206
|
-
return div(
|
|
207
|
-
{ className: "detail-item" },
|
|
208
|
-
div({ className: "detail-item-label" }, label),
|
|
209
|
-
valueEl,
|
|
107
|
+
span({ className: "level-label text-muted" }, "\u2014"),
|
|
210
108
|
);
|
|
211
109
|
}
|
|
212
110
|
|
|
@@ -1,72 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Error page components
|
|
3
|
+
*
|
|
4
|
+
* Re-exports from @forwardimpact/libui/components/error-page.
|
|
3
5
|
*/
|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
* @param {string} options.entityId - ID that was not found
|
|
12
|
-
* @param {string} options.backPath - Path to navigate back to
|
|
13
|
-
* @param {string} options.backText - Text for back link
|
|
14
|
-
*/
|
|
15
|
-
export function renderNotFound({ entityType, entityId, backPath, backText }) {
|
|
16
|
-
render(
|
|
17
|
-
div(
|
|
18
|
-
{ className: "error-message" },
|
|
19
|
-
h1({}, `${entityType} Not Found`),
|
|
20
|
-
p({}, `No ${entityType.toLowerCase()} found with ID: ${entityId}`),
|
|
21
|
-
a({ href: `#${backPath}` }, backText),
|
|
22
|
-
),
|
|
23
|
-
);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Create a not found error element (without rendering)
|
|
28
|
-
* @param {Object} options - Configuration options
|
|
29
|
-
* @param {string} options.entityType - Type of entity not found
|
|
30
|
-
* @param {string} options.entityId - ID that was not found
|
|
31
|
-
* @param {string} options.backPath - Path to navigate back to
|
|
32
|
-
* @param {string} options.backText - Text for back link
|
|
33
|
-
* @returns {HTMLElement}
|
|
34
|
-
*/
|
|
35
|
-
export function createNotFound({ entityType, entityId, backPath, backText }) {
|
|
36
|
-
return div(
|
|
37
|
-
{ className: "error-message" },
|
|
38
|
-
h1({}, `${entityType} Not Found`),
|
|
39
|
-
p({}, `No ${entityType.toLowerCase()} found with ID: ${entityId}`),
|
|
40
|
-
a({ href: `#${backPath}` }, backText),
|
|
41
|
-
);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Create an invalid state error element
|
|
46
|
-
* @param {Object} options - Configuration options
|
|
47
|
-
* @param {string} options.title - Error title
|
|
48
|
-
* @param {string} options.message - Error message
|
|
49
|
-
* @param {string} options.backPath - Path to navigate back to
|
|
50
|
-
* @param {string} options.backText - Text for back link
|
|
51
|
-
* @returns {HTMLElement}
|
|
52
|
-
*/
|
|
53
|
-
export function createErrorMessage({ title, message, backPath, backText }) {
|
|
54
|
-
return div(
|
|
55
|
-
{ className: "error-message" },
|
|
56
|
-
h1({}, title),
|
|
57
|
-
p({}, message),
|
|
58
|
-
a({ href: `#${backPath}` }, backText),
|
|
59
|
-
);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Render an invalid state error page
|
|
64
|
-
* @param {Object} options - Configuration options
|
|
65
|
-
* @param {string} options.title - Error title
|
|
66
|
-
* @param {string} options.message - Error message
|
|
67
|
-
* @param {string} options.backPath - Path to navigate back to
|
|
68
|
-
* @param {string} options.backText - Text for back link
|
|
69
|
-
*/
|
|
70
|
-
export function renderError({ title, message, backPath, backText }) {
|
|
71
|
-
render(createErrorMessage({ title, message, backPath, backText }));
|
|
72
|
-
}
|
|
7
|
+
export {
|
|
8
|
+
renderNotFound,
|
|
9
|
+
createNotFound,
|
|
10
|
+
createErrorMessage,
|
|
11
|
+
renderError,
|
|
12
|
+
} from "@forwardimpact/libui/components/error-page";
|
package/src/components/grid.js
CHANGED
|
@@ -1,109 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Grid components and utilities
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Grid size options
|
|
18
|
-
* @typedef {'xs' | 'sm' | 'md' | 'lg'} GridSize
|
|
19
|
-
*/
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Gap size options
|
|
23
|
-
* @typedef {'sm' | 'md' | 'lg' | 'xl'} GapSize
|
|
24
|
-
*/
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Create an auto-fit grid container
|
|
28
|
-
* @param {GridSize} size - Grid size variant (xs, sm, md, lg)
|
|
29
|
-
* @param {HTMLElement[]} children - Child elements to place in grid
|
|
30
|
-
* @param {Object} [options] - Optional configuration
|
|
31
|
-
* @param {string} [options.className] - Additional CSS classes
|
|
32
|
-
* @param {GapSize} [options.gap] - Override default gap (sm, md, lg, xl)
|
|
33
|
-
* @returns {HTMLElement}
|
|
34
|
-
*/
|
|
35
|
-
export function createAutoGrid(size, children, options = {}) {
|
|
36
|
-
const { className = "", gap } = options;
|
|
37
|
-
const classes = [`auto-grid-${size}`, gap ? `gap-${gap}` : "", className]
|
|
38
|
-
.filter(Boolean)
|
|
39
|
-
.join(" ");
|
|
40
|
-
|
|
41
|
-
return div({ className: classes }, ...children);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Create a fixed-column grid container
|
|
46
|
-
* @param {2 | 3 | 6} columns - Number of columns
|
|
47
|
-
* @param {HTMLElement[]} children - Child elements to place in grid
|
|
48
|
-
* @param {Object} [options] - Optional configuration
|
|
49
|
-
* @param {string} [options.className] - Additional CSS classes
|
|
50
|
-
* @returns {HTMLElement}
|
|
51
|
-
*/
|
|
52
|
-
export function createFixedGrid(columns, children, options = {}) {
|
|
53
|
-
const { className = "" } = options;
|
|
54
|
-
const classes = ["grid", `grid-${columns}`, className]
|
|
55
|
-
.filter(Boolean)
|
|
56
|
-
.join(" ");
|
|
57
|
-
|
|
58
|
-
return div({ className: classes }, ...children);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Create a grid for form selectors (discipline/level/track dropdowns)
|
|
63
|
-
* Uses auto-grid-sm (200px min)
|
|
64
|
-
* @param {HTMLElement[]} children - Form control elements
|
|
65
|
-
* @returns {HTMLElement}
|
|
66
|
-
*/
|
|
67
|
-
export function createSelectorGrid(children) {
|
|
68
|
-
return createAutoGrid("sm", children, { gap: "lg" });
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Create a grid for detail items (key-value pairs)
|
|
73
|
-
* Uses auto-grid-md (300px min)
|
|
74
|
-
* @param {HTMLElement[]} children - Detail item elements
|
|
75
|
-
* @returns {HTMLElement}
|
|
76
|
-
*/
|
|
77
|
-
export function createDetailGrid(children) {
|
|
78
|
-
return createAutoGrid("md", children);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Create a grid for radar charts or large content
|
|
83
|
-
* Uses auto-grid-lg (400px min)
|
|
84
|
-
* @param {HTMLElement[]} children - Large content elements
|
|
85
|
-
* @returns {HTMLElement}
|
|
86
|
-
*/
|
|
87
|
-
export function createRadarGrid(children) {
|
|
88
|
-
return createAutoGrid("lg", children);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Create a grid for compact stats
|
|
93
|
-
* Uses auto-grid-xs (150px min)
|
|
94
|
-
* @param {HTMLElement[]} children - Stat elements
|
|
95
|
-
* @returns {HTMLElement}
|
|
96
|
-
*/
|
|
97
|
-
export function createStatsGrid(children) {
|
|
98
|
-
return createAutoGrid("xs", children);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* Create a grid for card-like items (tips, expectations)
|
|
103
|
-
* Uses auto-grid-sm (200px min)
|
|
104
|
-
* @param {HTMLElement[]} children - Card elements
|
|
105
|
-
* @returns {HTMLElement}
|
|
106
|
-
*/
|
|
107
|
-
export function createCardGrid(children) {
|
|
108
|
-
return createAutoGrid("sm", children);
|
|
109
|
-
}
|
|
4
|
+
* Re-exports from @forwardimpact/libui/components/grid.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export {
|
|
8
|
+
createAutoGrid,
|
|
9
|
+
createFixedGrid,
|
|
10
|
+
createSelectorGrid,
|
|
11
|
+
createDetailGrid,
|
|
12
|
+
createRadarGrid,
|
|
13
|
+
createStatsGrid,
|
|
14
|
+
createCardGrid,
|
|
15
|
+
} from "@forwardimpact/libui/components/grid";
|