@netlisian/softconfig 0.1.5 → 0.1.6
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 +62 -122
- package/dist/puck/index.d.mts +1 -0
- package/dist/puck/index.d.ts +1 -0
- package/dist/puck/index.js +26 -13
- package/dist/puck/index.mjs +26 -13
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,122 +1,62 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
##
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
##
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
## Action Lifecycle Events
|
|
65
|
-
|
|
66
|
-
`SoftConfigProvider` supports `onActions` for lifecycle callbacks:
|
|
67
|
-
|
|
68
|
-
- `build` → when build mode starts
|
|
69
|
-
- `remodel` → when remodel mode starts
|
|
70
|
-
- `complete` → when a build/remodel is finalized
|
|
71
|
-
- `inspect` → when inspect is requested
|
|
72
|
-
- `demolish` → when a soft component is deleted
|
|
73
|
-
- `setDefaultVersion`, `decompose`, `cancel`, `publish`
|
|
74
|
-
|
|
75
|
-
Version-aware payloads are included for build finalization and inspection flows:
|
|
76
|
-
|
|
77
|
-
```ts
|
|
78
|
-
type ActionEventPayload =
|
|
79
|
-
| {
|
|
80
|
-
type: "remodel";
|
|
81
|
-
payload: {
|
|
82
|
-
id: string;
|
|
83
|
-
version?: string;
|
|
84
|
-
softComponent?: VersionedSoftComponent["versions"][string];
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
|
-
| {
|
|
88
|
-
type: "complete";
|
|
89
|
-
payload: {
|
|
90
|
-
id: string;
|
|
91
|
-
version: string;
|
|
92
|
-
componentData: Record<string, any>;
|
|
93
|
-
softComponent: VersionedSoftComponent["versions"][string];
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
| {
|
|
97
|
-
type: "inspect";
|
|
98
|
-
payload: {
|
|
99
|
-
id: string;
|
|
100
|
-
version?: string;
|
|
101
|
-
softComponent?: VersionedSoftComponent["versions"][string];
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
| {
|
|
105
|
-
type: "demolish";
|
|
106
|
-
payload: {
|
|
107
|
-
id: string;
|
|
108
|
-
};
|
|
109
|
-
};
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
This contract allows downstream consumers (for example, save/sync bridges) to persist using exact version metadata without relying on inferred/default versions.
|
|
113
|
-
|
|
114
|
-
## Development
|
|
115
|
-
|
|
116
|
-
- Build: `pnpm --filter @netlisian/softconfig build`
|
|
117
|
-
- Dev (watch): `pnpm --filter @netlisian/softconfig dev`
|
|
118
|
-
- Lint: `pnpm --filter @netlisian/softconfig lint`
|
|
119
|
-
|
|
120
|
-
## License
|
|
121
|
-
|
|
122
|
-
MIT
|
|
1
|
+
# @netlisian/soft-config
|
|
2
|
+
|
|
3
|
+
The core library for building and managing **Soft Components** within the Netlisian ecosystem. It provides type-safe field definitions, recursive mapping logic, and state management for the Puck editor.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @netlisian/soft-config
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Features
|
|
12
|
+
|
|
13
|
+
- **Soft Component Builder**: Easy-to-use interface for creating versioned components.
|
|
14
|
+
- **Dynamic Field Options**: Automatically generates dot-notated mapping paths for nested objects and arrays.
|
|
15
|
+
- **Custom Field Support**: Extend the editor with custom UI while maintaining return type safety.
|
|
16
|
+
- **Puck Overrides**: Pre-built component overrides (ActionBar, Header, ComponentList) to seamlessly integrate Soft Components into the Puck editor.
|
|
17
|
+
|
|
18
|
+
## Key Concepts
|
|
19
|
+
|
|
20
|
+
### Soft Component Definitions
|
|
21
|
+
|
|
22
|
+
A Soft Component consists of fields, default props, and typed components.
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
import { SoftFieldDefinition } from "@netlisian/soft-config";
|
|
26
|
+
|
|
27
|
+
const galleryField: SoftFieldDefinition = {
|
|
28
|
+
name: "gallery",
|
|
29
|
+
type: "array",
|
|
30
|
+
subFields: [
|
|
31
|
+
{ name: "src", type: "text" },
|
|
32
|
+
{ name: "alt", type: "text" }
|
|
33
|
+
]
|
|
34
|
+
};
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Custom Field Extensibility
|
|
38
|
+
|
|
39
|
+
Define custom field types with specified return types (`string`, `number`, `boolean`, `object`, `array`).
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
import { CustomFields } from "@netlisian/soft-config";
|
|
43
|
+
|
|
44
|
+
export const myCustomFields: CustomFields = {
|
|
45
|
+
"my-color": {
|
|
46
|
+
field: { type: "custom", render: () => <div>Color Picker</div> },
|
|
47
|
+
returnType: "string"
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Field Mapping
|
|
53
|
+
|
|
54
|
+
The library handles the logic for mapping configuration data to component props, including recursive array iteration using `[]` syntax (e.g., `features[].title`).
|
|
55
|
+
|
|
56
|
+
## Documentation
|
|
57
|
+
|
|
58
|
+
For detailed guides and API references, check the [Netlisian Docs](https://docs.netlisian.com).
|
|
59
|
+
|
|
60
|
+
## License
|
|
61
|
+
|
|
62
|
+
MIT
|
package/dist/puck/index.d.mts
CHANGED
|
@@ -342,6 +342,7 @@ type Overrides = {
|
|
|
342
342
|
props: RootData<AsFieldProps<WithChildren<BuilderRootConfig>>> | Promise<RootData<AsFieldProps<WithChildren<BuilderRootConfig>>>>;
|
|
343
343
|
readOnly: Readonly<Record<string, boolean>> | undefined;
|
|
344
344
|
};
|
|
345
|
+
mapComponentConfig?: (componentName: string, defaultConfig: ComponentConfig) => Partial<ComponentConfig>;
|
|
345
346
|
};
|
|
346
347
|
|
|
347
348
|
type Status = "building" | "remodeling" | "ready" | "inspecting";
|
package/dist/puck/index.d.ts
CHANGED
|
@@ -342,6 +342,7 @@ type Overrides = {
|
|
|
342
342
|
props: RootData<AsFieldProps<WithChildren<BuilderRootConfig>>> | Promise<RootData<AsFieldProps<WithChildren<BuilderRootConfig>>>>;
|
|
343
343
|
readOnly: Readonly<Record<string, boolean>> | undefined;
|
|
344
344
|
};
|
|
345
|
+
mapComponentConfig?: (componentName: string, defaultConfig: ComponentConfig) => Partial<ComponentConfig>;
|
|
345
346
|
};
|
|
346
347
|
|
|
347
348
|
type Status = "building" | "remodeling" | "ready" | "inspecting";
|
package/dist/puck/index.js
CHANGED
|
@@ -1644,21 +1644,29 @@ var import_uuid = require("uuid");
|
|
|
1644
1644
|
var generateId = (type) => type ? `${type}-${(0, import_uuid.v4)()}` : (0, import_uuid.v4)();
|
|
1645
1645
|
|
|
1646
1646
|
// src/puck/lib/component-key.ts
|
|
1647
|
-
var
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1647
|
+
var toSlug = (value) => {
|
|
1648
|
+
return value.replace(/([a-z])([A-Z])/g, "$1-$2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1-$2").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/-{2,}/g, "-").replace(/^-+|-+$/g, "");
|
|
1649
|
+
};
|
|
1650
|
+
var defaultComponentNameToKey = (displayName, context) => {
|
|
1651
|
+
var _a, _b;
|
|
1652
|
+
const registry = (_b = (_a = context.registryName) != null ? _a : context.registry) != null ? _b : "default";
|
|
1653
|
+
return `${toSlug(registry)}/${toSlug(displayName)}`;
|
|
1654
|
+
};
|
|
1655
|
+
var defaultComponentKeyToName = (key) => {
|
|
1656
|
+
const slashIndex = key.indexOf("/");
|
|
1657
|
+
const componentPart = slashIndex === -1 ? key : key.slice(slashIndex + 1);
|
|
1658
|
+
if (!componentPart) return "";
|
|
1659
|
+
return componentPart.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
1652
1660
|
};
|
|
1653
1661
|
var createComponentKeyFromName = (displayName, overrides, context) => {
|
|
1654
|
-
const key = overrides.componentNameToKey ? overrides.componentNameToKey(displayName, context) :
|
|
1662
|
+
const key = overrides.componentNameToKey ? overrides.componentNameToKey(displayName, context) : defaultComponentNameToKey(displayName, context);
|
|
1655
1663
|
return key.trim();
|
|
1656
1664
|
};
|
|
1657
1665
|
var getComponentNameFromKey = (key, overrides) => {
|
|
1658
1666
|
if (overrides == null ? void 0 : overrides.componentKeyToName) {
|
|
1659
1667
|
return overrides.componentKeyToName(key);
|
|
1660
1668
|
}
|
|
1661
|
-
return key;
|
|
1669
|
+
return defaultComponentKeyToName(key);
|
|
1662
1670
|
};
|
|
1663
1671
|
|
|
1664
1672
|
// src/puck/lib/soft-component-to-appstate.ts
|
|
@@ -2057,10 +2065,9 @@ var hydrateCustomField = (fieldName, field, fieldSettings, customFields) => {
|
|
|
2057
2065
|
label: field.label || customField.field.label || fieldName
|
|
2058
2066
|
});
|
|
2059
2067
|
};
|
|
2060
|
-
var createVersionedComponentConfig = (componentName, displayName, version, allVersions, config, softComponents, defaultProps, showVersioning = true, customFields) => {
|
|
2068
|
+
var createVersionedComponentConfig = (componentName, displayName, version, allVersions, config, softComponents, defaultProps, showVersioning = true, customFields, overrides) => {
|
|
2061
2069
|
var _a, _b;
|
|
2062
|
-
const
|
|
2063
|
-
return {
|
|
2070
|
+
const baseConfig = {
|
|
2064
2071
|
label: displayName,
|
|
2065
2072
|
fields: Object.fromEntries(
|
|
2066
2073
|
(Object.entries(
|
|
@@ -2104,12 +2111,16 @@ var createVersionedComponentConfig = (componentName, displayName, version, allVe
|
|
|
2104
2111
|
softComponentFields: versionedComponent.fields,
|
|
2105
2112
|
softComponentFieldSettings: versionedComponent.fieldSettings,
|
|
2106
2113
|
softSubComponent: versionedComponent.components,
|
|
2107
|
-
configComponents:
|
|
2114
|
+
configComponents: config.components,
|
|
2108
2115
|
props
|
|
2109
2116
|
}
|
|
2110
2117
|
);
|
|
2111
2118
|
}
|
|
2112
2119
|
};
|
|
2120
|
+
if (overrides == null ? void 0 : overrides.mapComponentConfig) {
|
|
2121
|
+
return __spreadValues(__spreadValues({}, baseConfig), overrides.mapComponentConfig(componentName, baseConfig));
|
|
2122
|
+
}
|
|
2123
|
+
return baseConfig;
|
|
2113
2124
|
};
|
|
2114
2125
|
|
|
2115
2126
|
// src/puck/lib/builder/sub-component-decomposer.tsx
|
|
@@ -2838,7 +2849,8 @@ function buildInitialSoftComponents(hardConfig, softComponents, overrides, showV
|
|
|
2838
2849
|
hydratedSoftComponents,
|
|
2839
2850
|
versionedComponent.defaultProps,
|
|
2840
2851
|
showVersioning,
|
|
2841
|
-
customFields
|
|
2852
|
+
customFields,
|
|
2853
|
+
overrides
|
|
2842
2854
|
);
|
|
2843
2855
|
componentConfigs[name] = newSoftComponentConfig;
|
|
2844
2856
|
buildingConfig.components[name] = newSoftComponentConfig;
|
|
@@ -2867,7 +2879,8 @@ function buildInitialSoftComponents(hardConfig, softComponents, overrides, showV
|
|
|
2867
2879
|
hydratedSoftComponents,
|
|
2868
2880
|
versionedComponent.defaultProps,
|
|
2869
2881
|
showVersioning,
|
|
2870
|
-
customFields
|
|
2882
|
+
customFields,
|
|
2883
|
+
overrides
|
|
2871
2884
|
);
|
|
2872
2885
|
componentConfigs[name] = newSoftComponentConfig;
|
|
2873
2886
|
}
|
package/dist/puck/index.mjs
CHANGED
|
@@ -1586,21 +1586,29 @@ import { v4 as uuidv4 } from "uuid";
|
|
|
1586
1586
|
var generateId = (type) => type ? `${type}-${uuidv4()}` : uuidv4();
|
|
1587
1587
|
|
|
1588
1588
|
// src/puck/lib/component-key.ts
|
|
1589
|
-
var
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1589
|
+
var toSlug = (value) => {
|
|
1590
|
+
return value.replace(/([a-z])([A-Z])/g, "$1-$2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1-$2").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/-{2,}/g, "-").replace(/^-+|-+$/g, "");
|
|
1591
|
+
};
|
|
1592
|
+
var defaultComponentNameToKey = (displayName, context) => {
|
|
1593
|
+
var _a, _b;
|
|
1594
|
+
const registry = (_b = (_a = context.registryName) != null ? _a : context.registry) != null ? _b : "default";
|
|
1595
|
+
return `${toSlug(registry)}/${toSlug(displayName)}`;
|
|
1596
|
+
};
|
|
1597
|
+
var defaultComponentKeyToName = (key) => {
|
|
1598
|
+
const slashIndex = key.indexOf("/");
|
|
1599
|
+
const componentPart = slashIndex === -1 ? key : key.slice(slashIndex + 1);
|
|
1600
|
+
if (!componentPart) return "";
|
|
1601
|
+
return componentPart.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
1594
1602
|
};
|
|
1595
1603
|
var createComponentKeyFromName = (displayName, overrides, context) => {
|
|
1596
|
-
const key = overrides.componentNameToKey ? overrides.componentNameToKey(displayName, context) :
|
|
1604
|
+
const key = overrides.componentNameToKey ? overrides.componentNameToKey(displayName, context) : defaultComponentNameToKey(displayName, context);
|
|
1597
1605
|
return key.trim();
|
|
1598
1606
|
};
|
|
1599
1607
|
var getComponentNameFromKey = (key, overrides) => {
|
|
1600
1608
|
if (overrides == null ? void 0 : overrides.componentKeyToName) {
|
|
1601
1609
|
return overrides.componentKeyToName(key);
|
|
1602
1610
|
}
|
|
1603
|
-
return key;
|
|
1611
|
+
return defaultComponentKeyToName(key);
|
|
1604
1612
|
};
|
|
1605
1613
|
|
|
1606
1614
|
// src/puck/lib/soft-component-to-appstate.ts
|
|
@@ -1999,10 +2007,9 @@ var hydrateCustomField = (fieldName, field, fieldSettings, customFields) => {
|
|
|
1999
2007
|
label: field.label || customField.field.label || fieldName
|
|
2000
2008
|
});
|
|
2001
2009
|
};
|
|
2002
|
-
var createVersionedComponentConfig = (componentName, displayName, version, allVersions, config, softComponents, defaultProps, showVersioning = true, customFields) => {
|
|
2010
|
+
var createVersionedComponentConfig = (componentName, displayName, version, allVersions, config, softComponents, defaultProps, showVersioning = true, customFields, overrides) => {
|
|
2003
2011
|
var _a, _b;
|
|
2004
|
-
const
|
|
2005
|
-
return {
|
|
2012
|
+
const baseConfig = {
|
|
2006
2013
|
label: displayName,
|
|
2007
2014
|
fields: Object.fromEntries(
|
|
2008
2015
|
(Object.entries(
|
|
@@ -2046,12 +2053,16 @@ var createVersionedComponentConfig = (componentName, displayName, version, allVe
|
|
|
2046
2053
|
softComponentFields: versionedComponent.fields,
|
|
2047
2054
|
softComponentFieldSettings: versionedComponent.fieldSettings,
|
|
2048
2055
|
softSubComponent: versionedComponent.components,
|
|
2049
|
-
configComponents:
|
|
2056
|
+
configComponents: config.components,
|
|
2050
2057
|
props
|
|
2051
2058
|
}
|
|
2052
2059
|
);
|
|
2053
2060
|
}
|
|
2054
2061
|
};
|
|
2062
|
+
if (overrides == null ? void 0 : overrides.mapComponentConfig) {
|
|
2063
|
+
return __spreadValues(__spreadValues({}, baseConfig), overrides.mapComponentConfig(componentName, baseConfig));
|
|
2064
|
+
}
|
|
2065
|
+
return baseConfig;
|
|
2055
2066
|
};
|
|
2056
2067
|
|
|
2057
2068
|
// src/puck/lib/builder/sub-component-decomposer.tsx
|
|
@@ -2780,7 +2791,8 @@ function buildInitialSoftComponents(hardConfig, softComponents, overrides, showV
|
|
|
2780
2791
|
hydratedSoftComponents,
|
|
2781
2792
|
versionedComponent.defaultProps,
|
|
2782
2793
|
showVersioning,
|
|
2783
|
-
customFields
|
|
2794
|
+
customFields,
|
|
2795
|
+
overrides
|
|
2784
2796
|
);
|
|
2785
2797
|
componentConfigs[name] = newSoftComponentConfig;
|
|
2786
2798
|
buildingConfig.components[name] = newSoftComponentConfig;
|
|
@@ -2809,7 +2821,8 @@ function buildInitialSoftComponents(hardConfig, softComponents, overrides, showV
|
|
|
2809
2821
|
hydratedSoftComponents,
|
|
2810
2822
|
versionedComponent.defaultProps,
|
|
2811
2823
|
showVersioning,
|
|
2812
|
-
customFields
|
|
2824
|
+
customFields,
|
|
2825
|
+
overrides
|
|
2813
2826
|
);
|
|
2814
2827
|
componentConfigs[name] = newSoftComponentConfig;
|
|
2815
2828
|
}
|