@colixsystems/widget-sdk 0.51.0 → 0.52.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/README.md CHANGED
@@ -51,7 +51,11 @@ See the design reference for the full architecture: [`docs/architecture/widget-m
51
51
 
52
52
  ## Status
53
53
 
54
- `v0.51.0` — pre-publish. The package surface (types, function names, export paths) is the v1 contract; runtime behaviour for some hooks is stubbed (each hook documents what's wired and what isn't). It is **not yet published to npm**.
54
+ `v0.52.0` — pre-publish. The package surface (types, function names, export paths) is the v1 contract; runtime behaviour for some hooks is stubbed (each hook documents what's wired and what isn't). It is **not yet published to npm**.
55
+
56
+ ### What's new in 0.52.0
57
+
58
+ **Lucide icon names accept any case (sc-2088).** A new `normalizeLucideIconName(name)` export maps a human-typed icon name to the PascalCase form Lucide exports its components under — `arrow-right`, `arrow_right`, `arrow right`, `arrowRight`, and `ArrowRight` all resolve to `ArrowRight`; `building-2` → `Building2`. The lucide.dev gallery and its copy button hand you kebab-case, so authors no longer have to hand-convert. The `<Icon name="…">` primitive normalizes its `name` before lookup, and the `icon` propertySchema type accepts any case. Additive — one new pure export; no existing export changed signature. `CONTRACT` is unchanged.
55
59
 
56
60
  ### What's new in 0.51.0
57
61
 
package/dist/icon.js CHANGED
@@ -16,10 +16,11 @@
16
16
 
17
17
  import React from "react";
18
18
  import * as LucideIcons from "lucide-react-native";
19
+ import { normalizeLucideIconName } from "./lucideIconName.js";
19
20
 
20
21
  export function Icon({ name, size, color }) {
21
- const candidate =
22
- typeof name === "string" && name.length > 0 ? LucideIcons[name] : null;
22
+ const resolved = normalizeLucideIconName(name);
23
+ const candidate = resolved ? LucideIcons[resolved] : null;
23
24
  const Component = candidate || LucideIcons.Square;
24
25
  const pixelSize = Number.isFinite(size) && size > 0 ? size : 24;
25
26
  return React.createElement(Component, {
package/dist/index.js CHANGED
@@ -70,3 +70,4 @@ export {
70
70
  } from "./primitives.js";
71
71
  export { lintSource, bannedIdentifiers } from "./linter.js";
72
72
  export { CONTRACT, isHookAllowed, requiredContextKeys } from "./contract.js";
73
+ export { normalizeLucideIconName } from "./lucideIconName.js";
@@ -66,3 +66,4 @@ export {
66
66
  } from "./primitives.native.js";
67
67
  export { lintSource, bannedIdentifiers } from "./linter.js";
68
68
  export { CONTRACT, isHookAllowed, requiredContextKeys } from "./contract.js";
69
+ export { normalizeLucideIconName } from "./lucideIconName.js";
@@ -0,0 +1,17 @@
1
+ // CommonJS twin of lucideIconName.js for the backend (the page service +
2
+ // any other Node consumer require this). Keep the two in sync — same
3
+ // algorithm, same behaviour. See lucideIconName.js for the rationale.
4
+ "use strict";
5
+
6
+ function normalizeLucideIconName(name) {
7
+ if (typeof name !== "string") return "";
8
+ const trimmed = name.trim();
9
+ if (trimmed === "") return "";
10
+ return trimmed
11
+ .split(/[-_\s]+/)
12
+ .filter(Boolean)
13
+ .map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1))
14
+ .join("");
15
+ }
16
+
17
+ module.exports = { normalizeLucideIconName };
@@ -0,0 +1,19 @@
1
+ // Normalize a human-typed Lucide icon name to the PascalCase form Lucide
2
+ // exports its components under. The lucide.dev gallery shows kebab-case
3
+ // (`arrow-right`) and its copy button hands you kebab-case, but
4
+ // `lucide-react` / `lucide-react-native` key their components in PascalCase
5
+ // (`ArrowRight`). This bridges the two so any of kebab / snake / spaced /
6
+ // camel / PascalCase resolves: `arrow-right`, `arrow_right`, `arrow right`,
7
+ // `arrowRight`, and `ArrowRight` all become `ArrowRight`; `building-2` becomes
8
+ // `Building2`. Non-strings and blanks return "" so callers fall back to a
9
+ // placeholder. Already-PascalCase names pass through unchanged.
10
+ export function normalizeLucideIconName(name) {
11
+ if (typeof name !== "string") return "";
12
+ const trimmed = name.trim();
13
+ if (trimmed === "") return "";
14
+ return trimmed
15
+ .split(/[-_\s]+/)
16
+ .filter(Boolean)
17
+ .map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1))
18
+ .join("");
19
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@colixsystems/widget-sdk",
3
- "version": "0.51.0",
3
+ "version": "0.52.0",
4
4
  "description": "Common widget interface for AppStudio. Implements WidgetManifest, WidgetContext, property schema, and helper hooks.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -42,7 +42,7 @@
42
42
  ],
43
43
  "scripts": {
44
44
  "build": "node scripts/build.js",
45
- "test": "node --test src/__tests__/contract.test.js src/__tests__/hooks-users.test.js src/__tests__/hooks-groups.test.js src/__tests__/hooks-schema.test.js src/__tests__/hooks-assets-by-tag.test.js src/__tests__/hooks-filestore-upload.test.js src/__tests__/hooks-mutation.test.js src/__tests__/hooks-record-permissions.test.js src/__tests__/hooks-geolocation.test.js src/__tests__/hooks-subscription.test.js src/__tests__/linter-users-scope.test.js src/__tests__/linter-comments.test.js src/__tests__/lucide-icon-names.test.js src/__tests__/manifest-actions.test.js src/__tests__/widget-translations.test.js src/__tests__/devserver.test.js src/__tests__/host-externals.test.js src/__tests__/datetimepicker.test.js"
45
+ "test": "node --test src/__tests__/contract.test.js src/__tests__/hooks-users.test.js src/__tests__/hooks-groups.test.js src/__tests__/hooks-schema.test.js src/__tests__/hooks-assets-by-tag.test.js src/__tests__/hooks-filestore-upload.test.js src/__tests__/hooks-mutation.test.js src/__tests__/hooks-record-permissions.test.js src/__tests__/hooks-geolocation.test.js src/__tests__/hooks-subscription.test.js src/__tests__/linter-users-scope.test.js src/__tests__/linter-comments.test.js src/__tests__/lucide-icon-names.test.js src/__tests__/lucideIconName.test.js src/__tests__/manifest-actions.test.js src/__tests__/widget-translations.test.js src/__tests__/devserver.test.js src/__tests__/host-externals.test.js src/__tests__/datetimepicker.test.js"
46
46
  },
47
47
  "engines": {
48
48
  "node": ">=18"