@ghxstship/xos-icons 0.0.0-stage → 4.16.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 GHXSTSHIP Industries LLC
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,29 @@
1
- # Temporary Holding Version
1
+ # @ghxstship/xos-icons
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ XOS glyph map and icon registry: the Lucide icon for every department, phase and record kind, the record state glyph shapes, and the closed set of icons XOS draws by name.
4
+
5
+ This is `@xos/icons` from the Atlas repository at release v4.16.0, published under the `@ghxstship` scope.
6
+ The archive holds the package's TypeScript source as the release tag does.
7
+
8
+ ## Install
9
+
10
+ The source imports its sibling packages as `@xos/*`, so install it under its workspace name with an npm alias, at an exact version:
11
+
12
+ ```json
13
+ {
14
+ "dependencies": {
15
+ "@xos/icons": "npm:@ghxstship/xos-icons@4.16.0"
16
+ }
17
+ }
18
+ ```
19
+
20
+ ## Build
21
+
22
+ The package ships TypeScript, so the consuming build transpiles it.
23
+
24
+ - In Next.js, list both names of every installed package in `transpilePackages`, for example `"@xos/icons"` and `"@ghxstship/xos-icons"`. pnpm resolves an alias to the published name, so the alias alone is not enough.
25
+ - The source imports its own files with `.ts` and `.tsx` extensions, so the consumer's `tsconfig.json` sets `allowImportingTsExtensions` (with `noEmit` and bundler module resolution).
26
+
27
+ ## License
28
+
29
+ MIT. See `LICENSE` and `THIRD_PARTY_NOTICES`.
@@ -0,0 +1,50 @@
1
+ Third-party notices for @xos/icons
2
+
3
+ The icon sprite, the glyph registry and the icon components in this package draw icons from lucide-react 1.53.0.
4
+ Its license follows in full.
5
+
6
+ ----------------------------------------------------------------------
7
+
8
+ ISC License
9
+
10
+ Copyright (c) 2026 Lucide Icons and Contributors
11
+
12
+ Permission to use, copy, modify, and/or distribute this software for any
13
+ purpose with or without fee is hereby granted, provided that the above
14
+ copyright notice and this permission notice appear in all copies.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
17
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
18
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
19
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
20
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
21
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
22
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23
+
24
+ ---
25
+
26
+ The following Lucide icons are derived from the Feather project:
27
+
28
+ airplay, alert-circle, alert-octagon, alert-triangle, aperture, arrow-down-circle, arrow-down-left, arrow-down-right, arrow-down, arrow-left-circle, arrow-left, arrow-right-circle, arrow-right, arrow-up-circle, arrow-up-left, arrow-up-right, arrow-up, at-sign, calendar, cast, check, chevron-down, chevron-left, chevron-right, chevron-up, chevrons-down, chevrons-left, chevrons-right, chevrons-up, circle, clipboard, clock, code, columns, command, compass, corner-down-left, corner-down-right, corner-left-down, corner-left-up, corner-right-down, corner-right-up, corner-up-left, corner-up-right, crosshair, database, divide-circle, divide-square, dollar-sign, download, external-link, feather, frown, hash, headphones, help-circle, info, italic, key, layout, life-buoy, link-2, link, loader, lock, log-in, log-out, maximize, meh, minimize, minimize-2, minus-circle, minus-square, minus, monitor, moon, more-horizontal, more-vertical, move, music, navigation-2, navigation, octagon, pause-circle, percent, plus-circle, plus-square, plus, power, radio, rss, search, server, share, shopping-bag, sidebar, smartphone, smile, square, table-2, tablet, target, terminal, trash-2, trash, triangle, tv, type, upload, x-circle, x-octagon, x-square, x, zoom-in, zoom-out
29
+
30
+ The MIT License (MIT) (for the icons listed above)
31
+
32
+ Copyright (c) 2013-present Cole Bemis
33
+
34
+ Permission is hereby granted, free of charge, to any person obtaining a copy
35
+ of this software and associated documentation files (the "Software"), to deal
36
+ in the Software without restriction, including without limitation the rights
37
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
38
+ copies of the Software, and to permit persons to whom the Software is
39
+ furnished to do so, subject to the following conditions:
40
+
41
+ The above copyright notice and this permission notice shall be included in all
42
+ copies or substantial portions of the Software.
43
+
44
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
45
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
46
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
47
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
48
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
49
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
50
+ SOFTWARE.
package/package.json CHANGED
@@ -1,6 +1,30 @@
1
1
  {
2
2
  "name": "@ghxstship/xos-icons",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "4.16.0",
4
+ "description": "XOS glyph map and icon registry: the Lucide icon for every department, phase and record kind, the record state glyph shapes, and the closed set of icons XOS draws by name.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "exports": {
8
+ ".": "./src/index.ts",
9
+ "./glyphs": "./src/glyphs.ts",
10
+ "./names": "./src/names.ts",
11
+ "./sprite.svg": {
12
+ "types": "./src/sprite.d.ts",
13
+ "default": "./src/sprite.generated.svg"
14
+ },
15
+ "./map.json": "./src/map.json"
16
+ },
17
+ "dependencies": {
18
+ "lucide-react": "1.53.0"
19
+ },
20
+ "sideEffects": false,
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "git+https://github.com/ghxstship/atlas.git",
24
+ "directory": "packages/icons"
25
+ },
26
+ "publishConfig": {
27
+ "access": "public",
28
+ "provenance": false
29
+ }
30
+ }
@@ -0,0 +1,5 @@
1
+ # Icons the Places and Safety pages (A09) draw by name that no other registry lists: tree nodes,
2
+ # empty states and the Safety landing tiles. One lucide-react name per line.
3
+ ClipboardCheck
4
+ FileBadge
5
+ Square
@@ -0,0 +1,2 @@
1
+ # A128: the role lens under the org switcher (apps/atlas/components/shell/role-lens-switch.tsx).
2
+ UserRoundSearch
@@ -0,0 +1,14 @@
1
+ # Icons the Finance and Reports pages (A15) draw by name that no other registry lists: toolbar
2
+ # actions and empty states. One lucide-react name per line.
3
+ ArrowRightLeft
4
+ Banknote
5
+ ClipboardPaste
6
+ FilePlus2
7
+ FileSpreadsheet
8
+ Handshake
9
+ Package
10
+ BarChart3
11
+ Gauge
12
+ Grid3x3
13
+ ShoppingCart
14
+ FileCheck
@@ -0,0 +1,23 @@
1
+ # Icons Atlas pages draw by name that were missing from the registry, so they rendered as blank
2
+ # boxes (A35, RRR-79): found by the accessibility sweep (Folder, ListPlus, ListVideo, Table2) and by a
3
+ # scan of every icon="..." prop in Atlas, Gateway and @xos/ui. One lucide-react name per line.
4
+ Award
5
+ CheckCircle2
6
+ CloudLightning
7
+ Copy
8
+ FileOutput
9
+ Filter
10
+ Folder
11
+ FolderOpen
12
+ LayoutTemplate
13
+ Link
14
+ ListPlus
15
+ ListVideo
16
+ PackageSearch
17
+ Palmtree
18
+ Scale
19
+ ScrollText
20
+ ShieldAlert
21
+ Siren
22
+ Table2
23
+ UserMinus
@@ -0,0 +1,2 @@
1
+ # Icons A36 pages draw by name (custom object empty state). One lucide-react name per line.
2
+ Box
@@ -0,0 +1,4 @@
1
+ # A61 (RRR-106): the curated feed reaction glyphs (Section 11.10 item 8).
2
+ Heart
3
+ Laugh
4
+ PartyPopper
@@ -0,0 +1,11 @@
1
+ # Icons the Assets pages (A12) draw by name through @xos/ui. One lucide-react name per line.
2
+ Archive
3
+ ArrowRightLeft
4
+ ListChecks
5
+ Package
6
+ Pencil
7
+ Plus
8
+ SearchX
9
+ TriangleAlert
10
+ Wrench
11
+ X
@@ -0,0 +1,38 @@
1
+ # Icons the Atlas shell draws by name: sidebar items, chrome actions and shell states (A06).
2
+ Activity
3
+ BookOpen
4
+ Boxes
5
+ Briefcase
6
+ CalendarDays
7
+ ChartColumn
8
+ Circle
9
+ CircleCheck
10
+ CircleUserRound
11
+ Clapperboard
12
+ FileText
13
+ Folder
14
+ FolderKanban
15
+ GripVertical
16
+ HardHat
17
+ House
18
+ IdCard
19
+ Inbox
20
+ Landmark
21
+ Library
22
+ List
23
+ ListChecks
24
+ LogOut
25
+ MapPin
26
+ Menu
27
+ PackageCheck
28
+ Search
29
+ SearchX
30
+ Settings
31
+ ShieldCheck
32
+ ShoppingCart
33
+ Star
34
+ Store
35
+ Truck
36
+ UserRound
37
+ Users
38
+ UtensilsCrossed
@@ -0,0 +1,3 @@
1
+ # Icons B3 draws by name (RRR-227, ADR 0142): the segment library and the showcaller portal.
2
+ Layers
3
+ Timer
@@ -0,0 +1,21 @@
1
+ # Icons the Gateway app draws by name that no other registry lists: destinations, engagement
2
+ # tabs, empty states and actions (A27). One lucide-react name per line.
3
+ ArrowLeftRight
4
+ BedDouble
5
+ BellPlus
6
+ BookmarkCheck
7
+ BriefcaseBusiness
8
+ CircleUser
9
+ FileBarChart
10
+ FileCheck
11
+ FileDiff
12
+ Flag
13
+ FolderLock
14
+ Gavel
15
+ Gift
16
+ ListMusic
17
+ ListOrdered
18
+ Mail
19
+ MailCheck
20
+ MessagesSquare
21
+ Receipt
@@ -0,0 +1,9 @@
1
+ # Icons the Atlas Logistics and Hospitality pages draw by name (A11): empty states and the drawer
2
+ # close control they open. One lucide-react name per line.
3
+ ClipboardList
4
+ ConciergeBell
5
+ FolderPlus
6
+ Hotel
7
+ Plane
8
+ Warehouse
9
+ X
@@ -0,0 +1,7 @@
1
+ # Icons the Marketing layer of packages/ui draws by name (design handoff section 10): the comparison
2
+ # cell marks and the surface icons of its previews. One lucide-react name per line.
3
+ CircleDashed
4
+ CircleDot
5
+ CircleMinus
6
+ DoorOpen
7
+ LayoutDashboard
@@ -0,0 +1,98 @@
1
+ # Icons packages/ui draws by name: component chrome, feedback tones, pickers and the Icon aliases
2
+ # (more, alert, check-circle, pin, home, undo). Owner: A05. One lucide-react name per line.
3
+ # Canon glyphs (departments, phases, record kinds) come from src/map.json and are not repeated here.
4
+ AlarmClock
5
+ ArrowDown
6
+ ArrowLeft
7
+ ArrowRight
8
+ ArrowUp
9
+ ArrowUpRight
10
+ AudioLines
11
+ BadgeCheck
12
+ Bell
13
+ Bold
14
+ Bookmark
15
+ Building2
16
+ Calendar
17
+ CalendarClock
18
+ CalendarPlus
19
+ CalendarRange
20
+ ChartColumn
21
+ Check
22
+ ChevronDown
23
+ ChevronLeft
24
+ ChevronRight
25
+ ChevronsUpDown
26
+ Circle
27
+ CircleAlert
28
+ CircleCheck
29
+ CircleHelp
30
+ CircleX
31
+ Clock
32
+ Compass
33
+ Download
34
+ Ellipsis
35
+ ExternalLink
36
+ Eye
37
+ File
38
+ FileText
39
+ FolderKanban
40
+ Globe
41
+ Hash
42
+ House
43
+ Image
44
+ Inbox
45
+ Info
46
+ Italic
47
+ Landmark
48
+ LayoutGrid
49
+ LifeBuoy
50
+ Link2
51
+ List
52
+ ListFilter
53
+ Lock
54
+ Map
55
+ MapPin
56
+ Maximize2
57
+ Megaphone
58
+ Menu
59
+ MessageSquare
60
+ Minus
61
+ Navigation
62
+ OctagonAlert
63
+ Paperclip
64
+ Pencil
65
+ Play
66
+ Plus
67
+ Radio
68
+ RefreshCw
69
+ ScanLine
70
+ Search
71
+ SearchX
72
+ Send
73
+ Shapes
74
+ SlidersHorizontal
75
+ Sparkles
76
+ Star
77
+ Sun
78
+ SunMedium
79
+ Table
80
+ ThumbsUp
81
+ Trash2
82
+ TriangleAlert
83
+ Undo2
84
+ Upload
85
+ User
86
+ UserPlus
87
+ Wallet
88
+ WifiOff
89
+ ZoomIn
90
+ ZoomOut
91
+ Camera
92
+ Coffee
93
+ Flashlight
94
+ Nfc
95
+ PenLine
96
+ Phone
97
+ Smartphone
98
+ X
@@ -0,0 +1,32 @@
1
+ # Icons A31 (Views, Help and Support) draws by name: the saved views menu, the view registry's view
2
+ # types (packages/schemas/views.yaml), the help panel, tours, tips and support. One lucide-react name
3
+ # per line.
4
+ Bookmark
5
+ BookmarkPlus
6
+ CalendarRange
7
+ ChartColumn
8
+ ChartGantt
9
+ Columns3
10
+ Grid3x3
11
+ Inbox
12
+ LayoutGrid
13
+ List
14
+ ListTree
15
+ Map
16
+ MapPinned
17
+ Network
18
+ PanelLeft
19
+ Pin
20
+ PinOff
21
+ RefreshCw
22
+ Rss
23
+ Share2
24
+ Sheet
25
+ Table
26
+ Trash2
27
+ Users
28
+ ArrowLeft
29
+ BookOpen
30
+ CircleHelp
31
+ LifeBuoy
32
+ Play
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Writes src/names.generated.ts, src/registry.generated.ts and src/sprite.generated.svg: the closed set of lucide-react icons XOS draws by name, imported
3
+ * one by one so bundlers keep only these icons (RRR-70). Sources are every registry/<owner>.txt
4
+ * (one PascalCase lucide-react name per line, `#` starts a comment) plus every glyph in src/map.json.
5
+ * Each owner keeps its own list, so parallel branches never conflict in a shared file (ADR 0021);
6
+ * on a conflict in the generated file, rerun this script.
7
+ *
8
+ * Usage: node scripts/generate-registry.mjs [--check]
9
+ * With --check, writes nothing and exits 1 when the generated file is out of date or a name does
10
+ * not exist in the pinned lucide-react.
11
+ */
12
+ import { readFileSync, readdirSync, writeFileSync } from "node:fs";
13
+ import { createRequire } from "node:module";
14
+ import { dirname, join } from "node:path";
15
+ import { fileURLToPath } from "node:url";
16
+ import * as prettier from "prettier";
17
+
18
+ const root = join(dirname(fileURLToPath(import.meta.url)), "..");
19
+ const lucide = createRequire(import.meta.url)("lucide-react");
20
+
21
+ const owners = new Map();
22
+ function add(name, owner) {
23
+ if (!owners.has(name)) owners.set(name, new Set());
24
+ owners.get(name).add(owner);
25
+ }
26
+
27
+ const map = JSON.parse(readFileSync(join(root, "src/map.json"), "utf8"));
28
+ for (const table of [map.departments, map.phases, map.recordKinds]) {
29
+ for (const name of Object.values(table)) add(name, "map.json");
30
+ }
31
+
32
+ const registryDir = join(root, "registry");
33
+ for (const file of readdirSync(registryDir)
34
+ .filter((f) => f.endsWith(".txt"))
35
+ .sort()) {
36
+ const lines = readFileSync(join(registryDir, file), "utf8").split(/\r?\n/);
37
+ for (const raw of lines) {
38
+ const name = raw.replace(/#.*/, "").trim();
39
+ if (name) add(name, file);
40
+ }
41
+ }
42
+
43
+ const problems = [];
44
+ for (const [name, from] of owners) {
45
+ const where = [...from].join(", ");
46
+ if (!/^[A-Z][A-Za-z0-9]*$/.test(name)) {
47
+ problems.push(`${name} (${where}) is not a PascalCase lucide-react name`);
48
+ } else if (name.startsWith("Lucide") || name.endsWith("Icon") || name === "Icon") {
49
+ problems.push(`${name} (${where}) is an alias form; list the base name`);
50
+ } else if (typeof lucide[name] !== "object" && typeof lucide[name] !== "function") {
51
+ problems.push(`${name} (${where}) does not exist in lucide-react ${map.library.version}`);
52
+ }
53
+ }
54
+ if (problems.length > 0) {
55
+ console.error(`Icon registry has ${problems.length} invalid names:\n ${problems.join("\n ")}`);
56
+ process.exit(1);
57
+ }
58
+
59
+ const names = [...owners.keys()].sort();
60
+ const header = `/* Generated by scripts/generate-registry.mjs from registry/*.txt and src/map.json. Do not edit; run \`pnpm --filter @xos/icons generate:registry\`. */`;
61
+
62
+ const namesSource = `${header}
63
+
64
+ /** Every icon name XOS draws by name, sorted. Imports nothing, so a bundle that only checks names stays small. */
65
+ export const registeredIconNames = ${JSON.stringify(names)} as const;
66
+
67
+ export type RegisteredIconName = (typeof registeredIconNames)[number];
68
+ `;
69
+
70
+ const registrySource = `${header}
71
+ import type { LucideIcon } from "lucide-react";
72
+ import { ${names.map((n) => `${n} as Lucide${n}`).join(", ")} } from "lucide-react";
73
+ import { registeredIconNames, type RegisteredIconName } from "./names.generated.ts";
74
+
75
+ export { registeredIconNames, type RegisteredIconName };
76
+
77
+ /** The lucide-react component for each registered name. Only these icons reach a bundle. */
78
+ export const iconRegistry: Readonly<Record<RegisteredIconName, LucideIcon>> = /* @__PURE__ */ Object.freeze({ ${names
79
+ .map((n) => `${n}: Lucide${n}`)
80
+ .join(", ")} });
81
+ `;
82
+
83
+ /** XML attribute text: lucide's path data never needs more than these escapes. */
84
+ function attr(value) {
85
+ return String(value).replaceAll("&", "&amp;").replaceAll('"', "&quot;").replaceAll("<", "&lt;");
86
+ }
87
+
88
+ /**
89
+ * The web icon sprite (ADR 0027): one <symbol> per registered icon, drawn from the same pinned
90
+ * lucide-react data as the components. Symbols carry only geometry, so the referencing <svg> sets
91
+ * stroke, size and color for each use.
92
+ */
93
+ function symbol(name) {
94
+ const data = lucide[name].render({}, null).props.icon;
95
+ const size = data.size ?? 24;
96
+ const children = data.node
97
+ .map(([tag, attrs]) => {
98
+ const text = Object.entries(attrs)
99
+ .filter(([k]) => k !== "key")
100
+ .map(([k, v]) => ` ${k}="${attr(v)}"`)
101
+ .join("");
102
+ return `<${tag}${text}/>`;
103
+ })
104
+ .join("");
105
+ return `<symbol id="${name}" viewBox="0 0 ${size} ${size}">${children}</symbol>`;
106
+ }
107
+ // Width and height let Next.js read the file as a static image import; uses ignore them.
108
+ const sprite = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">\n${names.map(symbol).join("\n")}\n</svg>\n`;
109
+
110
+ const outputs = [];
111
+ for (const [file, source] of [
112
+ ["src/names.generated.ts", namesSource],
113
+ ["src/registry.generated.ts", registrySource],
114
+ ]) {
115
+ const path = join(root, file);
116
+ const config = (await prettier.resolveConfig(path)) ?? {};
117
+ outputs.push([file, await prettier.format(source, { ...config, filepath: path })]);
118
+ }
119
+ outputs.push(["src/sprite.generated.svg", sprite]);
120
+
121
+ if (process.argv.includes("--check")) {
122
+ const stale = outputs.filter(([file, output]) => {
123
+ try {
124
+ return readFileSync(join(root, file), "utf8") !== output;
125
+ } catch {
126
+ return true;
127
+ }
128
+ });
129
+ if (stale.length > 0) {
130
+ console.error(
131
+ `${stale.map(([file]) => file).join(", ")} out of date. Run pnpm --filter @xos/icons generate:registry.`,
132
+ );
133
+ process.exit(1);
134
+ }
135
+ } else {
136
+ for (const [file, output] of outputs) writeFileSync(join(root, file), output);
137
+ console.log(`Wrote ${names.length} icons to the names, registry and sprite files in src/.`);
138
+ }
package/src/glyphs.ts ADDED
@@ -0,0 +1,78 @@
1
+ import map from "./map.json" with { type: "json" };
2
+
3
+ /**
4
+ * XOS glyph map (design handoff, section 2): the lucide-react icon for each department, phase and
5
+ * record kind, keyed by canon code, and the shape each record state draws. src/map.json is the
6
+ * single source; every Lucide name in it resolves in the pinned lucide-react.
7
+ */
8
+
9
+ export type DepartmentCode = keyof typeof map.departments;
10
+ export type PhaseCode = keyof typeof map.phases;
11
+ export type RecordKind = keyof typeof map.recordKinds;
12
+ export type RecordState = keyof typeof map.stateIcons;
13
+
14
+ /** A Lucide component name used by an XOS glyph, in PascalCase (`Hammer`). */
15
+ export type GlyphIconName =
16
+ | (typeof map.departments)[DepartmentCode]
17
+ | (typeof map.phases)[PhaseCode]
18
+ | (typeof map.recordKinds)[RecordKind];
19
+
20
+ /** The shape a record state icon draws. State icons are custom (StateIcon), not Lucide. */
21
+ export type StateGlyph = (typeof map.stateIcons)[RecordState];
22
+
23
+ /** Icon library facts the glyphs are drawn with: package, pinned version, license and stroke width. */
24
+ export const iconLibrary: Readonly<typeof map.library> = map.library;
25
+
26
+ export const departmentCodes = Object.keys(map.departments) as DepartmentCode[];
27
+ export const phaseCodes = Object.keys(map.phases) as PhaseCode[];
28
+ export const recordKinds = Object.keys(map.recordKinds) as RecordKind[];
29
+ export const recordStates = Object.keys(map.stateIcons) as RecordState[];
30
+
31
+ function has<T extends object>(table: T, key: string): key is Extract<keyof T, string> {
32
+ return Object.hasOwn(table, key);
33
+ }
34
+
35
+ export function isDepartmentCode(value: string): value is DepartmentCode {
36
+ return has(map.departments, value);
37
+ }
38
+
39
+ export function isPhaseCode(value: string): value is PhaseCode {
40
+ return has(map.phases, value);
41
+ }
42
+
43
+ export function isRecordKind(value: string): value is RecordKind {
44
+ return has(map.recordKinds, value);
45
+ }
46
+
47
+ export function isRecordState(value: string): value is RecordState {
48
+ return has(map.stateIcons, value);
49
+ }
50
+
51
+ /** Lucide icon for a department code (`"4000"` is Tent). */
52
+ export function departmentIcon(code: DepartmentCode): GlyphIconName {
53
+ return map.departments[code];
54
+ }
55
+
56
+ /** Lucide icon for a phase code (`"BLD"` is Hammer). */
57
+ export function phaseIcon(code: PhaseCode): GlyphIconName {
58
+ return map.phases[code];
59
+ }
60
+
61
+ /** Lucide icon for a record kind (`"Task"` is SquareCheck). */
62
+ export function recordKindIcon(kind: RecordKind): GlyphIconName {
63
+ return map.recordKinds[kind];
64
+ }
65
+
66
+ /** Shape drawn by the record state icon (`"blocked"` is an octagon). */
67
+ export function stateGlyph(state: RecordState): StateGlyph {
68
+ return map.stateIcons[state];
69
+ }
70
+
71
+ /** Every distinct Lucide name the glyph map uses, sorted. */
72
+ export const glyphIconNames: readonly GlyphIconName[] = [
73
+ ...new Set<GlyphIconName>([
74
+ ...Object.values(map.departments),
75
+ ...Object.values(map.phases),
76
+ ...Object.values(map.recordKinds),
77
+ ]),
78
+ ].sort();
package/src/index.ts ADDED
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @xos/icons: the glyph map, the icon names XOS draws, the lucide-react components behind them
3
+ * (native and server use) and the web sprite (`@xos/icons/sprite.svg`). Web bundles import the
4
+ * `glyphs` and `names` entries, which pull in no icon components (ADR 0027).
5
+ */
6
+ export * from "./glyphs.ts";
7
+ export * from "./names.ts";
8
+ export * from "./registry.ts";