rw-elements-tools 1.2.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.
Files changed (185) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +1333 -0
  3. package/bin/cli.js +213 -0
  4. package/build-properties.js +654 -0
  5. package/build-shared-hooks.js +253 -0
  6. package/config.js +148 -0
  7. package/controls/Animations/AnimationEffects.js +111 -0
  8. package/controls/Animations/AnimationSettings.js +437 -0
  9. package/controls/Animations/Reveals.js +168 -0
  10. package/controls/Animations/ScrollAnimation_Opacity.js +15 -0
  11. package/controls/Animations/ScrollAnimation_Rotate.js +17 -0
  12. package/controls/Animations/ScrollAnimation_Scale.js +18 -0
  13. package/controls/Animations/ScrollAnimation_Translate.js +31 -0
  14. package/controls/Background/Background.js +66 -0
  15. package/controls/Background/BackgroundButton.js +69 -0
  16. package/controls/Background/BackgroundColor.js +28 -0
  17. package/controls/Background/BackgroundContainer.js +73 -0
  18. package/controls/Background/BackgroundGradient.js +149 -0
  19. package/controls/Background/BackgroundImage.js +108 -0
  20. package/controls/Background/BackgroundOnlyColor.js +53 -0
  21. package/controls/Background/BackgroundTransparent.js +66 -0
  22. package/controls/Background/BackgroundVideo.js +9 -0
  23. package/controls/Background/Color.js +52 -0
  24. package/controls/Background/Gradient.js +263 -0
  25. package/controls/Background/GradientContainer.js +263 -0
  26. package/controls/Background/Image.js +269 -0
  27. package/controls/Background/Image_CMS.js +305 -0
  28. package/controls/Background/SVG.js +235 -0
  29. package/controls/Background/Video.js +29 -0
  30. package/controls/Borders/Border.js +114 -0
  31. package/controls/Borders/BorderColor.js +25 -0
  32. package/controls/Borders/BorderRadius.js +19 -0
  33. package/controls/Borders/BorderStyle.js +26 -0
  34. package/controls/Borders/BorderWidth.js +20 -0
  35. package/controls/Borders/Borders.js +69 -0
  36. package/controls/Borders/BordersContainer.js +90 -0
  37. package/controls/Borders/BordersInput.js +107 -0
  38. package/controls/Borders/Outline.js +100 -0
  39. package/controls/Borders/OutlineColor.js +25 -0
  40. package/controls/Borders/OutlineOffset.js +13 -0
  41. package/controls/Borders/OutlineStyle.js +26 -0
  42. package/controls/Borders/OutlineWidth.js +13 -0
  43. package/controls/Effects/BackdropBlur.js +11 -0
  44. package/controls/Effects/Blur.js +11 -0
  45. package/controls/Effects/BoxShadow.js +15 -0
  46. package/controls/Effects/Brightness.js +11 -0
  47. package/controls/Effects/DropShadow.js +14 -0
  48. package/controls/Effects/Effects.js +71 -0
  49. package/controls/Effects/Filters.js +114 -0
  50. package/controls/Effects/Opacity.js +14 -0
  51. package/controls/Effects/Saturate.js +11 -0
  52. package/controls/Layout/AspectRatio.js +53 -0
  53. package/controls/Layout/Container.js +24 -0
  54. package/controls/Layout/Hidden.js +9 -0
  55. package/controls/Layout/Inset.js +15 -0
  56. package/controls/Layout/Isolation.js +25 -0
  57. package/controls/Layout/Layout.js +38 -0
  58. package/controls/Layout/Overflow.js +33 -0
  59. package/controls/Layout/Position.js +37 -0
  60. package/controls/Layout/TopRightBottomLeft.js +90 -0
  61. package/controls/Layout/Visibility.js +25 -0
  62. package/controls/Layout/ZIndex.js +36 -0
  63. package/controls/Overlay/Color.js +52 -0
  64. package/controls/Overlay/Gradient.js +298 -0
  65. package/controls/Overlay/Image.js +226 -0
  66. package/controls/Overlay/Overlay.js +66 -0
  67. package/controls/Sizing/Height.js +18 -0
  68. package/controls/Sizing/MaxHeight.js +17 -0
  69. package/controls/Sizing/MaxWidth.js +17 -0
  70. package/controls/Sizing/MinHeight.js +18 -0
  71. package/controls/Sizing/MinWidth.js +18 -0
  72. package/controls/Sizing/Sizing.js +66 -0
  73. package/controls/Sizing/SizingContainer.js +122 -0
  74. package/controls/Sizing/SizingImage.js +75 -0
  75. package/controls/Sizing/SizingInput.js +71 -0
  76. package/controls/Sizing/SizingSVG.js +74 -0
  77. package/controls/Sizing/Width.js +18 -0
  78. package/controls/Spacing/Margin.js +17 -0
  79. package/controls/Spacing/Padding.js +17 -0
  80. package/controls/Spacing/Spacing.js +23 -0
  81. package/controls/Spacing/SpacingButton.js +42 -0
  82. package/controls/Spacing/SpacingContainer.js +32 -0
  83. package/controls/Spacing/SpacingInput.js +42 -0
  84. package/controls/Transforms/Rotate.js +13 -0
  85. package/controls/Transforms/Scale.js +13 -0
  86. package/controls/Transforms/Skew.js +25 -0
  87. package/controls/Transforms/TransformOrigin.js +12 -0
  88. package/controls/Transforms/Transforms.js +98 -0
  89. package/controls/Transforms/Translate.js +26 -0
  90. package/controls/Transitions/Delay.js +13 -0
  91. package/controls/Transitions/Duration.js +13 -0
  92. package/controls/Transitions/Property.js +42 -0
  93. package/controls/Transitions/TimingFunction.js +44 -0
  94. package/controls/Transitions/Transitions.js +20 -0
  95. package/controls/alignment/AlignContent.js +48 -0
  96. package/controls/alignment/AlignItems.js +64 -0
  97. package/controls/alignment/AlignSelf.js +34 -0
  98. package/controls/alignment/JustifyContent.js +44 -0
  99. package/controls/alignment/JustifyItems.js +32 -0
  100. package/controls/alignment/JustifySelf.js +34 -0
  101. package/controls/core/CSSClasses.js +11 -0
  102. package/controls/core/ControlType.js +25 -0
  103. package/controls/core/HTMLTag.js +80 -0
  104. package/controls/core/HoverGroup.js +38 -0
  105. package/controls/core/ID.js +12 -0
  106. package/controls/core/Image.js +95 -0
  107. package/controls/core/MenuItem.js +187 -0
  108. package/controls/core/ObjectFit.js +32 -0
  109. package/controls/core/ObjectPosition.js +65 -0
  110. package/controls/grid-flex/ActAsGridOrFlexItem.js +54 -0
  111. package/controls/grid-flex/ColEnd.js +28 -0
  112. package/controls/grid-flex/ColStart.js +27 -0
  113. package/controls/grid-flex/Columns.js +38 -0
  114. package/controls/grid-flex/FlexDirection.js +27 -0
  115. package/controls/grid-flex/FlexItem.js +106 -0
  116. package/controls/grid-flex/GridItem.js +41 -0
  117. package/controls/grid-flex/Order.js +45 -0
  118. package/controls/grid-flex/RowEnd.js +28 -0
  119. package/controls/grid-flex/RowStart.js +27 -0
  120. package/controls/grid-flex/Rows.js +38 -0
  121. package/controls/index.js +187 -0
  122. package/controls/interactive/ButtonFontAndTextStyles.js +208 -0
  123. package/controls/interactive/Filter.js +54 -0
  124. package/controls/interactive/InputFontAndTextStyles.js +156 -0
  125. package/controls/interactive/Link.js +13 -0
  126. package/controls/typography/HeadingColor.js +112 -0
  127. package/controls/typography/TextColor.js +51 -0
  128. package/controls/typography/TextDecoration.js +99 -0
  129. package/controls/typography/TextFontsAndTextStyles.js +243 -0
  130. package/controls/typography/TextSimple.js +55 -0
  131. package/controls/typography/TextStyles.js +55 -0
  132. package/controls/typography/Typography.js +13 -0
  133. package/index.js +19 -0
  134. package/package.json +55 -0
  135. package/properties/BackgroundType.js +18 -0
  136. package/properties/ButtonSize.js +19 -0
  137. package/properties/ContainerHeights.js +23 -0
  138. package/properties/ContainerWidths.js +27 -0
  139. package/properties/FontWeight.js +16 -0
  140. package/properties/GradientDirection.js +39 -0
  141. package/properties/LetterSpacing.js +13 -0
  142. package/properties/LineHeight.js +13 -0
  143. package/properties/RevealAnimations.js +12 -0
  144. package/properties/Slider.js +10 -0
  145. package/properties/TextAlign.js +23 -0
  146. package/properties/TransformOrigins.js +43 -0
  147. package/properties/TransitionNames.js +20 -0
  148. package/properties/index.js +13 -0
  149. package/shared-hooks/animations/globalAnimations.js +141 -0
  150. package/shared-hooks/animations/globalReveal.js +48 -0
  151. package/shared-hooks/background/globalBackground.js +306 -0
  152. package/shared-hooks/background/globalBgImageFetchPriority.js +34 -0
  153. package/shared-hooks/borders/globalBorders.js +85 -0
  154. package/shared-hooks/borders/globalOutline.js +39 -0
  155. package/shared-hooks/core/addPrefixToTailwindClasses.js +24 -0
  156. package/shared-hooks/core/advancedClasses.js +5 -0
  157. package/shared-hooks/core/classnames.js +92 -0
  158. package/shared-hooks/core/getHoverPrefix.js +21 -0
  159. package/shared-hooks/core/globalHTMLTag.js +17 -0
  160. package/shared-hooks/core/injectPrefixOnDarkModeColors.js +6 -0
  161. package/shared-hooks/effects/globalEffects.js +45 -0
  162. package/shared-hooks/effects/globalFilters.js +80 -0
  163. package/shared-hooks/effects/globalOverlay.js +166 -0
  164. package/shared-hooks/interactive/globalFilter.js +24 -0
  165. package/shared-hooks/interactive/globalLink.js +23 -0
  166. package/shared-hooks/layout/globalActAsGridOrFlexItem.js +66 -0
  167. package/shared-hooks/layout/globalLayout.js +50 -0
  168. package/shared-hooks/navigation/globalMenuItem.js +35 -0
  169. package/shared-hooks/navigation/globalNavItems.js +60 -0
  170. package/shared-hooks/navigation/globalNavTitle.js +23 -0
  171. package/shared-hooks/sizing/aspectRatioClasses.js +20 -0
  172. package/shared-hooks/sizing/globalSizing.js +19 -0
  173. package/shared-hooks/sizing/globalSizingContainer.js +40 -0
  174. package/shared-hooks/sizing/objectClasses.js +9 -0
  175. package/shared-hooks/spacing/globalSpacing.js +13 -0
  176. package/shared-hooks/spacing/globalSpacingMargin.js +11 -0
  177. package/shared-hooks/spacing/globalSpacingPadding.js +11 -0
  178. package/shared-hooks/transforms/globalTransforms.js +78 -0
  179. package/shared-hooks/transitions/getAlpineTransitionAttributesDesktop.js +111 -0
  180. package/shared-hooks/transitions/getAlpineTransitionAttributesMobile.js +110 -0
  181. package/shared-hooks/transitions/globalTransitions.js +48 -0
  182. package/shared-hooks/typography/globalButtonFontAndTextStyles.js +65 -0
  183. package/shared-hooks/typography/globalHeadingColor.js +69 -0
  184. package/shared-hooks/typography/globalInputFontAndTextStyles.js +40 -0
  185. package/shared-hooks/typography/globalTextFontsAndTextStyles.js +47 -0
package/README.md ADDED
@@ -0,0 +1,1333 @@
1
+ # rw-elements-tools
2
+
3
+ **The official build toolkit for creating RapidWeaver Elements**
4
+
5
+ Build powerful, reusable web components for RapidWeaver without the complexity. This toolkit handles the heavy lifting so you can focus on what matters: creating great elements.
6
+
7
+ ---
8
+
9
+ ## What is rw-elements-tools?
10
+
11
+ rw-elements-tools is a development toolkit that simplifies the process of creating custom elements for [RapidWeaver](https://www.realmacsoftware.com/rapidweaver/), the popular Mac website builder. It provides:
12
+
13
+ - **A powerful CLI** for building and watching your element files
14
+ - **Ready-to-use controls** for common UI patterns (colors, spacing, typography, and more)
15
+ - **Shared utilities** for generating Tailwind CSS classes
16
+ - **Smart optimization** that automatically removes unused code from your builds
17
+
18
+ ## Who is this for?
19
+
20
+ - **Theme developers** who want to create custom RapidWeaver elements
21
+ - **Agencies** building bespoke elements for client projects
22
+ - **Developers** looking to extend RapidWeaver's capabilities
23
+ - **Anyone** who wants to contribute elements to the RapidWeaver ecosystem
24
+
25
+ ## Why use rw-elements-tools?
26
+
27
+ | Without rw-elements-tools | With rw-elements-tools |
28
+ |--------------------------|----------------------|
29
+ | Manually write complex JSON config files | Use intuitive JavaScript configuration |
30
+ | Copy/paste utility code between elements | Import from a shared library |
31
+ | Bloated output with unused code | Automatic dead code elimination |
32
+ | Manual rebuilds on every change | Watch mode for instant updates |
33
+
34
+ ---
35
+
36
+ ## Installation
37
+
38
+ ```bash
39
+ npm install --save-dev rw-elements-tools
40
+ ```
41
+
42
+ ## Quick Start
43
+
44
+ ### Step 1: Set Up Your Project
45
+
46
+ Create a new directory for your element pack project and initialize it:
47
+
48
+ ```bash
49
+ mkdir my-element-pack
50
+ cd my-element-pack
51
+ npm init -y
52
+ npm install --save-dev rw-elements-tools
53
+ ```
54
+
55
+ ### Step 2: Create the Required Directory Structure
56
+
57
+ Your project needs a `packs` folder containing your element pack(s). Each pack follows this structure:
58
+
59
+ ```
60
+ my-element-pack/
61
+ ├── package.json
62
+ ├── packs/ # Default packs directory
63
+ │ └── MyPack.elementsdevpack/ # Your pack (must end in .elementsdevpack)
64
+ │ └── components/
65
+ │ └── com.yourcompany.elementname/ # Component folder (must start with com.)
66
+ │ ├── properties.config.json # Source config (you edit this)
67
+ │ ├── properties.json # Generated output (don't edit)
68
+ │ ├── hooks.source.js # Source hooks (you edit this)
69
+ │ └── hooks.js # Generated output (don't edit)
70
+ └── node_modules/
71
+ ```
72
+
73
+ **Key naming conventions:**
74
+ - Pack folders must end with `.elementsdevpack`
75
+ - Component folders must start with `com.` (e.g., `com.mycompany.button`)
76
+ - Source files: `properties.config.json` and `hooks.source.js`
77
+ - Generated files: `properties.json` and `hooks.js`
78
+
79
+ ### Step 3: Create Your First Element
80
+
81
+ Create the folder structure for your first element:
82
+
83
+ ```bash
84
+ mkdir -p packs/MyPack.elementsdevpack/components/com.mycompany.button
85
+ ```
86
+
87
+ Create a minimal `properties.config.json`:
88
+
89
+ ```json
90
+ {
91
+ "groups": [
92
+ {
93
+ "title": "Content",
94
+ "icon": "text.alignleft",
95
+ "properties": [
96
+ {
97
+ "title": "Button Text",
98
+ "id": "buttonText",
99
+ "text": {
100
+ "default": "Click Me"
101
+ }
102
+ }
103
+ ]
104
+ }
105
+ ]
106
+ }
107
+ ```
108
+
109
+ Create a `hooks.source.js` that uses the shared hook utilities:
110
+
111
+ ```javascript
112
+ function transformHook(rw) {
113
+ // Props are accessed via rw.props - property IDs from properties.config.json
114
+ const { buttonText } = rw.props;
115
+
116
+ // Build CSS classes using the shared classnames utility
117
+ const classes = classnames()
118
+ .add(globalSpacing(rw))
119
+ .add(globalBgColor(rw))
120
+ .toString();
121
+
122
+ return {
123
+ classes,
124
+ buttonText
125
+ };
126
+ }
127
+
128
+ exports.transformHook = transformHook;
129
+ ```
130
+
131
+ > **Note:** The `buttonText` prop corresponds to the `"id": "buttonText"` defined in `properties.config.json`. All property IDs become available on `rw.props`. Functions like `classnames()`, `globalSpacing()`, and `globalBgColor()` come from the shared hooks library—no imports needed.
132
+
133
+ ### Step 4: Add Build Scripts
134
+
135
+ Add these scripts to your `package.json`:
136
+
137
+ ```json
138
+ {
139
+ "scripts": {
140
+ "build": "rw-build all",
141
+ "build:properties": "rw-build properties",
142
+ "build:hooks": "rw-build hooks",
143
+ "dev": "rw-build all --watch"
144
+ }
145
+ }
146
+ ```
147
+
148
+ ### Step 5: Build Your Elements
149
+
150
+ ```bash
151
+ # One-time build
152
+ npm run build
153
+
154
+ # Or watch for changes during development
155
+ npm run dev
156
+ ```
157
+
158
+ That's it! The build tool will generate `properties.json` and `hooks.js` files in each component folder.
159
+
160
+ ---
161
+
162
+ ### Build Commands Reference
163
+
164
+ ```bash
165
+ # Build all properties and hooks
166
+ npx rw-build all
167
+
168
+ # Build properties only
169
+ npx rw-build properties
170
+
171
+ # Build hooks only
172
+ npx rw-build hooks
173
+
174
+ # Watch for changes
175
+ npx rw-build all --watch # Watch both properties and hooks
176
+ npx rw-build properties --watch # Watch properties only
177
+ npx rw-build hooks --watch # Watch hooks only
178
+ ```
179
+
180
+ ## Configuration
181
+
182
+ The packs directory can be configured via multiple methods (in priority order):
183
+
184
+ ### 1. CLI Argument (highest priority)
185
+
186
+ ```bash
187
+ rw-build all --packs ./my-elements
188
+ ```
189
+
190
+ ### 2. Environment Variable
191
+
192
+ ```bash
193
+ RW_PACKS_DIR=./my-elements npm run build
194
+ ```
195
+
196
+ ### 3. package.json
197
+
198
+ ```json
199
+ {
200
+ "rw-elements-tools": {
201
+ "packsDir": "./my-elements"
202
+ }
203
+ }
204
+ ```
205
+
206
+ ### 4. Config File
207
+
208
+ ```javascript
209
+ // rw-elements-tools.config.js
210
+ export default {
211
+ packsDir: './my-elements'
212
+ }
213
+ ```
214
+
215
+ ### 5. Default
216
+
217
+ If no configuration is provided, looks for `./packs` in the project root.
218
+
219
+ ---
220
+
221
+ ## Table of Contents
222
+
223
+ 1. [Overview](#overview)
224
+ 2. [Directory Structure](#directory-structure)
225
+ 3. [Properties Build System](#properties-build-system)
226
+ 4. [Shared Hooks Build System](#shared-hooks-build-system)
227
+ 5. [Controls](#controls)
228
+ 6. [Properties](#properties)
229
+ 7. [Configuration File Format](#configuration-file-format)
230
+ 8. [Adding New Controls](#adding-new-controls)
231
+ 9. [Adding New Properties](#adding-new-properties)
232
+ 10. [Adding Shared Hooks](#adding-shared-hooks)
233
+ 11. [Advanced Features](#advanced-features)
234
+ 12. [Build Commands](#build-commands)
235
+ 13. [Programmatic Usage](#programmatic-usage)
236
+
237
+ ---
238
+
239
+ ## Overview
240
+
241
+ The build system processes `properties.config.json` files located in element component directories and generates expanded `properties.json` files. This allows developers to:
242
+
243
+ - **Reuse common UI controls** across multiple elements via `globalControl` references
244
+ - **Share property definitions** (like spacing values, font weights) via `use` references
245
+ - **Override defaults** per-element while maintaining a single source of truth
246
+ - **Apply theme defaults** for consistent theming across elements
247
+
248
+ ### Data Flow
249
+
250
+ ```
251
+ properties.config.json Controls (controls/)
252
+ │ │
253
+ ▼ ▼
254
+ ┌─────────────────────────────────────┐
255
+ │ build-properties.js │
256
+ │ • Expands globalControl references │
257
+ │ • Resolves 'use' property refs │
258
+ │ • Applies overrides & defaults │
259
+ │ • Injects Advanced group controls │
260
+ └─────────────────────────────────────┘
261
+
262
+
263
+ properties.json
264
+ (consumed by RapidWeaver)
265
+ ```
266
+
267
+ ---
268
+
269
+ ## Directory Structure
270
+
271
+ ```
272
+ rw-elements-tools/
273
+ ├── bin/
274
+ │ └── cli.js # CLI entry point (rw-build command)
275
+ ├── build-properties.js # Properties build script
276
+ ├── build-shared-hooks.js # Shared hooks build script
277
+ ├── config.js # Configuration resolver
278
+ ├── index.js # Package entry point
279
+ ├── package.json # npm package config
280
+ ├── README.md # This documentation
281
+ ├── controls/ # Reusable UI control definitions
282
+ │ ├── index.js # Exports all controls
283
+ │ ├── alignment/ # Flexbox/Grid alignment controls
284
+ │ ├── Animations/ # Animation and scroll animation controls
285
+ │ ├── Background/ # Background color, image, gradient, video
286
+ │ ├── Borders/ # Border and outline controls
287
+ │ ├── core/ # Essential controls (ID, CSSClasses, etc.)
288
+ │ ├── Effects/ # Box shadow, opacity, filters, blur
289
+ │ ├── grid-flex/ # Grid and flexbox item controls
290
+ │ ├── interactive/ # Button, input, link, filter controls
291
+ │ ├── Layout/ # Position, overflow, visibility, z-index
292
+ │ ├── Overlay/ # Overlay color, gradient, image
293
+ │ ├── Sizing/ # Width, height, min/max sizing
294
+ │ ├── Spacing/ # Margin and padding controls
295
+ │ ├── Transforms/ # Rotate, scale, skew, translate
296
+ │ ├── Transitions/ # Transition timing and properties
297
+ │ └── typography/ # Text color, decoration, styles
298
+ ├── properties/ # Reusable property value definitions
299
+ │ ├── index.js # Exports all properties
300
+ │ ├── Slider.js # Slider value ranges
301
+ │ ├── FontWeight.js # Font weight options
302
+ │ └── ... # Other property definitions
303
+ └── shared-hooks/ # Shared JavaScript hook functions
304
+ ├── animations/ # Animation and reveal functions
305
+ ├── background/ # Background processing functions
306
+ ├── borders/ # Border and outline functions
307
+ ├── core/ # Essential utilities (classnames, etc.)
308
+ ├── effects/ # Visual effects (opacity, filters)
309
+ ├── interactive/ # Link and filter functions
310
+ ├── layout/ # Layout and positioning
311
+ ├── navigation/ # Navigation component styles
312
+ ├── sizing/ # Dimensions and aspect ratios
313
+ ├── spacing/ # Margin and padding functions
314
+ ├── transforms/ # CSS transform functions
315
+ ├── transitions/ # CSS and Alpine transitions
316
+ └── typography/ # Text and font style functions
317
+ ```
318
+
319
+ ---
320
+
321
+ ## Properties Build System
322
+
323
+ ### Entry Point
324
+
325
+ The properties build script is executed via:
326
+
327
+ ```bash
328
+ cd src
329
+ npm run build
330
+ ```
331
+
332
+ This runs `node build.js` which:
333
+
334
+ 1. **Finds all config files** matching the glob pattern:
335
+ ```
336
+ ../**/*.elementsdevpack/components/com.**/**/properties.config.json
337
+ ```
338
+
339
+ 2. **Processes each config file** through the following pipeline:
340
+ - Parse the JSON configuration
341
+ - Set up the Advanced group with injected controls (CSSClasses, ID)
342
+ - Process each property group
343
+ - Expand `globalControl` references
344
+ - Resolve `use` property references
345
+ - Apply overrides and theme defaults
346
+ - Write the output to `properties.json`
347
+
348
+ ### Processing Pipeline
349
+
350
+ For each property in a config file:
351
+
352
+ ```
353
+ ┌─────────────────────────────────────────────────────────────┐
354
+ │ 1. Check for globalControl │
355
+ │ └─ If present: Load control from Controls registry │
356
+ │ └─ If absent: Pass through with 'use' resolution only │
357
+ ├─────────────────────────────────────────────────────────────┤
358
+ │ 2. Deep clone the control (avoid mutations) │
359
+ ├─────────────────────────────────────────────────────────────┤
360
+ │ 3. Apply property overrides │
361
+ │ └─ String values: Replace directly │
362
+ │ └─ Object values: Shallow merge │
363
+ ├─────────────────────────────────────────────────────────────┤
364
+ │ 4. Apply default values │
365
+ │ └─ Primitive defaults: Set control.default │
366
+ │ └─ Object defaults: Merge into theme properties │
367
+ ├─────────────────────────────────────────────────────────────┤
368
+ │ 5. Apply theme defaults │
369
+ │ └─ themeColor, themeFont, themeBorderRadius, etc. │
370
+ ├─────────────────────────────────────────────────────────────┤
371
+ │ 6. Transform IDs using {{value}} template │
372
+ │ └─ "prefix{{value}}Suffix" → "prefixControlIdSuffix" │
373
+ ├─────────────────────────────────────────────────────────────┤
374
+ │ 7. Process nested globalControls recursively │
375
+ ├─────────────────────────────────────────────────────────────┤
376
+ │ 8. Resolve 'use' references to Properties │
377
+ └─────────────────────────────────────────────────────────────┘
378
+ ```
379
+
380
+ ---
381
+
382
+ ## Shared Hooks Build System
383
+
384
+ The shared hooks build system combines reusable JavaScript utility functions with component-specific hook code, then applies dead code elimination to produce optimized output.
385
+
386
+ ### Overview
387
+
388
+ ```
389
+ shared-hooks/**/*.js Component hooks.source.js
390
+ │ │
391
+ ▼ ▼
392
+ ┌─────────────────────────────────────────┐
393
+ │ build-shared-hooks.js │
394
+ │ • Concatenates shared + component code │
395
+ │ • Applies esbuild dead code elimination │
396
+ │ • Keeps only code reachable from │
397
+ │ transformHook function │
398
+ └─────────────────────────────────────────┘
399
+
400
+
401
+ hooks.js (optimized)
402
+ (consumed by RapidWeaver)
403
+ ```
404
+
405
+ ### How It Works
406
+
407
+ 1. **Find all source files**: Scans `packs/` for `hooks.source.js` files
408
+ 2. **Read shared hooks**: Loads all `.js` files from `shared-hooks/` and its subfolders
409
+ 3. **Concatenate**: Combines shared code + component code
410
+ 4. **Dead code elimination**: Uses esbuild to remove unused functions
411
+ 5. **Output**: Writes optimized `hooks.js` to each component
412
+
413
+ ### Shared Hook Organization
414
+
415
+ Shared hooks are organized into category subfolders:
416
+
417
+ | Folder | Purpose | Example Functions |
418
+ |--------|---------|-------------------|
419
+ | `core/` | Essential utilities | `classnames`, `getHoverPrefix`, `globalHTMLTag` |
420
+ | `layout/` | Layout and positioning | `globalLayout`, `globalActAsGridOrFlexItem` |
421
+ | `sizing/` | Dimensions and aspect ratios | `globalSizing`, `aspectRatioClasses` |
422
+ | `spacing/` | Margin and padding | `globalSpacing`, `globalSpacingMargin` |
423
+ | `background/` | Background styles | `globalBackground`, `globalBgImageFetchPriority` |
424
+ | `borders/` | Borders and outlines | `globalBorders`, `globalOutline` |
425
+ | `effects/` | Visual effects | `globalEffects`, `globalFilters`, `globalOverlay` |
426
+ | `typography/` | Text and font styles | `globalTextFontsAndTextStyles`, `globalHeadingColor` |
427
+ | `transforms/` | CSS transforms | `globalTransforms` |
428
+ | `transitions/` | CSS/Alpine transitions | `globalTransitions`, `getAlpineTransitionAttributesMobile` |
429
+ | `animations/` | Animations and reveals | `globalAnimations`, `globalReveal` |
430
+ | `navigation/` | Navigation styles | `globalNavItems`, `globalMenuItem` |
431
+ | `interactive/` | Links and filters | `globalLink`, `globalFilter` |
432
+
433
+ ### Component Hook Files
434
+
435
+ Each component that needs hooks creates a `hooks.source.js` file:
436
+
437
+ ```javascript
438
+ // packs/Core.elementsdevpack/components/com.realmacsoftware.button/hooks.source.js
439
+
440
+ function transformHook(rw) {
441
+ // Use any shared hook functions here
442
+ const classes = classnames(rw.props.customClasses)
443
+ .add(globalSpacing(rw))
444
+ .toString();
445
+
446
+ return {
447
+ classes
448
+ };
449
+ }
450
+
451
+ exports.transformHook = transformHook;
452
+ ```
453
+
454
+ ### Key Points
455
+
456
+ - **Entry point**: The `transformHook` function is the only exported function
457
+ - **Dead code elimination**: Only code reachable from `transformHook` is kept
458
+ - **No manual imports**: Shared code is concatenated, not imported
459
+ - **Auto-generated**: Output `hooks.js` files are marked "do not edit"
460
+
461
+ ### Build Commands
462
+
463
+ ```bash
464
+ # Build all hooks once
465
+ npm run build:hooks
466
+
467
+ # Watch for changes
468
+ npm run build:hooks:watch
469
+
470
+ # Using npm scripts
471
+ npm run build:hooks
472
+ ```
473
+
474
+ ---
475
+
476
+ ## Controls
477
+
478
+ Controls are reusable UI component definitions that map to RapidWeaver's property inspector UI elements.
479
+
480
+ ### Control Structure
481
+
482
+ A control is a JavaScript object (or array of objects) that defines:
483
+
484
+ ```javascript
485
+ // Simple control (single object)
486
+ const FlexDirection = {
487
+ title: "Direction",
488
+ id: "flexDirection",
489
+ select: {
490
+ default: "flex-col",
491
+ items: [
492
+ { value: "flex-col", title: "Column" },
493
+ { value: "flex-row", title: "Row" },
494
+ ],
495
+ },
496
+ };
497
+
498
+ export default FlexDirection;
499
+ ```
500
+
501
+ ```javascript
502
+ // Compound control (array of objects)
503
+ const Link = [
504
+ {
505
+ title: "Link",
506
+ heading: {}
507
+ },
508
+ {
509
+ title: "To",
510
+ id: "globalLink",
511
+ link: {}
512
+ }
513
+ ];
514
+
515
+ export default Link;
516
+ ```
517
+
518
+ ### UI Element Types
519
+
520
+ Controls can use these UI element types:
521
+
522
+ | Type | Description | Example |
523
+ |------|-------------|---------|
524
+ | `select` | Dropdown menu | `{ select: { default: "value", items: [...] } }` |
525
+ | `segmented` | Segmented button control | `{ segmented: { default: "a", items: [...] } }` |
526
+ | `switch` | Boolean toggle | `{ switch: { default: false } }` |
527
+ | `slider` | Numeric slider | `{ slider: { default: 50, min: 0, max: 100 } }` |
528
+ | `number` | Numeric input | `{ number: { default: 0 } }` |
529
+ | `text` | Text input | `{ text: { default: "" } }` |
530
+ | `textArea` | Multi-line text | `{ textArea: { default: "" } }` |
531
+ | `link` | Link picker | `{ link: {} }` |
532
+ | `resource` | Resource/image picker | `{ resource: {} }` |
533
+ | `heading` | Section heading (no value) | `{ heading: {} }` |
534
+ | `divider` | Visual separator | `{ divider: {} }` |
535
+ | `information` | Info text | `{ information: {} }` |
536
+ | `themeColor` | Theme color picker | `{ themeColor: { default: {...} } }` |
537
+ | `themeSpacing` | Theme spacing picker | `{ themeSpacing: { mode: "single" } }` |
538
+ | `themeBorderRadius` | Border radius picker | `{ themeBorderRadius: {...} }` |
539
+ | `themeBorderWidth` | Border width picker | `{ themeBorderWidth: {...} }` |
540
+ | `themeShadow` | Shadow picker | `{ themeShadow: {...} }` |
541
+
542
+ ### Control Properties
543
+
544
+ | Property | Type | Description |
545
+ |----------|------|-------------|
546
+ | `title` | string | Display label in the UI |
547
+ | `id` | string | Property identifier (used in templates) |
548
+ | `format` | string | CSS class format, e.g., `"gap-x-{{value}}"` |
549
+ | `visible` | string | Visibility condition, e.g., `"otherProp == 'value'"` |
550
+ | `responsive` | boolean | Whether control is responsive (default: true) |
551
+ | `globalControl` | string | Reference to another control (nested) |
552
+
553
+ ### Nested globalControls
554
+
555
+ Controls can reference other controls for composition:
556
+
557
+ ```javascript
558
+ const Borders = [
559
+ {
560
+ globalControl: "ControlType",
561
+ id: "{{value}}Borders",
562
+ },
563
+ {
564
+ globalControl: "BorderStyle",
565
+ visible: "globalControlTypeBorders == 'static'",
566
+ },
567
+ {
568
+ globalControl: "BorderColor",
569
+ visible: "globalControlTypeBorders == 'static'",
570
+ },
571
+ ];
572
+ ```
573
+
574
+ ---
575
+
576
+ ## Properties
577
+
578
+ Properties are reusable value definitions (like enums or option lists) that can be referenced using the `use` key.
579
+
580
+ ### Property Structure
581
+
582
+ ```javascript
583
+ // properties/FontWeight.js
584
+ const FontWeight = {
585
+ default: "normal",
586
+ items: [
587
+ { value: "thin", title: "Thin" },
588
+ { value: "light", title: "Light" },
589
+ { value: "normal", title: "Normal" },
590
+ { value: "medium", title: "Medium" },
591
+ { value: "semibold", title: "Semibold" },
592
+ { value: "bold", title: "Bold" },
593
+ ],
594
+ };
595
+
596
+ export default FontWeight;
597
+ ```
598
+
599
+ ### Using Properties in Controls
600
+
601
+ Reference a property using the `use` key:
602
+
603
+ ```javascript
604
+ const TextWeight = {
605
+ title: "Weight",
606
+ id: "textWeight",
607
+ select: {
608
+ use: "FontWeight" // Merges FontWeight's items and default
609
+ }
610
+ };
611
+ ```
612
+
613
+ The build system will merge the referenced property, with local values taking precedence:
614
+
615
+ ```javascript
616
+ // Output
617
+ {
618
+ title: "Weight",
619
+ id: "textWeight",
620
+ select: {
621
+ default: "normal",
622
+ items: [
623
+ { value: "thin", title: "Thin" },
624
+ // ... etc
625
+ ]
626
+ }
627
+ }
628
+ ```
629
+
630
+ ---
631
+
632
+ ## Configuration File Format
633
+
634
+ ### properties.config.json Structure
635
+
636
+ ```json
637
+ {
638
+ "groups": [
639
+ {
640
+ "title": "Group Title",
641
+ "icon": "sf-symbol-name",
642
+ "properties": [
643
+ // Property definitions
644
+ ]
645
+ }
646
+ ]
647
+ }
648
+ ```
649
+
650
+ ### Using globalControl
651
+
652
+ Reference a control by name:
653
+
654
+ ```json
655
+ {
656
+ "globalControl": "Spacing"
657
+ }
658
+ ```
659
+
660
+ ### Overriding Control Properties
661
+
662
+ Add properties alongside `globalControl` to override:
663
+
664
+ ```json
665
+ {
666
+ "globalControl": "BorderRadius",
667
+ "title": "Corner Radius",
668
+ "default": {
669
+ "base": {
670
+ "topLeft": "lg",
671
+ "topRight": "lg",
672
+ "bottomLeft": "none",
673
+ "bottomRight": "none"
674
+ }
675
+ }
676
+ }
677
+ ```
678
+
679
+ ### ID Templates with {{value}}
680
+
681
+ Transform the control's ID using a template:
682
+
683
+ ```json
684
+ {
685
+ "globalControl": "Spacing",
686
+ "id": "card{{value}}"
687
+ }
688
+ ```
689
+
690
+ If the Spacing control has `id: "globalPadding"`, the output becomes `id: "cardGlobalPadding"`.
691
+
692
+ ### Theme Defaults
693
+
694
+ Override theme-related properties:
695
+
696
+ ```json
697
+ {
698
+ "globalControl": "Background_Color",
699
+ "themeColor": {
700
+ "default": {
701
+ "name": "brand",
702
+ "brightness": 500
703
+ }
704
+ }
705
+ }
706
+ ```
707
+
708
+ Supported theme properties:
709
+ - `themeColor`
710
+ - `themeFont`
711
+ - `themeBorderRadius`
712
+ - `themeBorderWidth`
713
+ - `themeSpacing`
714
+ - `themeShadow`
715
+ - `themeTextStyle`
716
+
717
+ ### Inline Properties
718
+
719
+ Properties without `globalControl` are passed through with `use` resolution:
720
+
721
+ ```json
722
+ {
723
+ "title": "Custom Width",
724
+ "id": "customWidth",
725
+ "slider": {
726
+ "use": "Slider",
727
+ "default": 100,
728
+ "min": 0,
729
+ "max": 500
730
+ }
731
+ }
732
+ ```
733
+
734
+ ---
735
+
736
+ ## Adding New Controls
737
+
738
+ ### Step 1: Create the Control File
739
+
740
+ Create a new file in the appropriate `controls/` subdirectory:
741
+
742
+ ```javascript
743
+ // controls/Effects/NewEffect.js
744
+
745
+ const NewEffect = {
746
+ title: "Effect Intensity",
747
+ id: "effectIntensity",
748
+ format: "effect-[{{value}}%]",
749
+ slider: {
750
+ default: 50,
751
+ min: 0,
752
+ max: 100,
753
+ round: true,
754
+ units: "%"
755
+ }
756
+ };
757
+
758
+ export default NewEffect;
759
+ ```
760
+
761
+ ### Step 2: Export from index.js
762
+
763
+ Add the export to `controls/index.js`:
764
+
765
+ ```javascript
766
+ // In the appropriate section
767
+ export { default as NewEffect } from "./Effects/NewEffect.js";
768
+ ```
769
+
770
+ ### Step 3: Use in Config Files
771
+
772
+ Reference in any `properties.config.json`:
773
+
774
+ ```json
775
+ {
776
+ "globalControl": "NewEffect"
777
+ }
778
+ ```
779
+
780
+ ### Step 4: Rebuild
781
+
782
+ ```bash
783
+ cd src
784
+ npm run build
785
+ ```
786
+
787
+ ### Creating Compound Controls
788
+
789
+ For controls with multiple UI elements:
790
+
791
+ ```javascript
792
+ // controls/interactive/CustomButton.js
793
+
794
+ const CustomButton = [
795
+ {
796
+ title: "Button Settings",
797
+ heading: {}
798
+ },
799
+ {
800
+ title: "Style",
801
+ id: "buttonStyle",
802
+ segmented: {
803
+ default: "solid",
804
+ items: [
805
+ { value: "solid", title: "Solid" },
806
+ { value: "outline", title: "Outline" },
807
+ { value: "ghost", title: "Ghost" }
808
+ ]
809
+ }
810
+ },
811
+ {
812
+ title: "Size",
813
+ id: "buttonSize",
814
+ select: {
815
+ use: "ButtonSize"
816
+ }
817
+ }
818
+ ];
819
+
820
+ export default CustomButton;
821
+ ```
822
+
823
+ ### Creating Controls with Nested globalControls
824
+
825
+ ```javascript
826
+ // controls/Layout/CustomLayout.js
827
+
828
+ const CustomLayout = [
829
+ {
830
+ globalControl: "ControlType",
831
+ id: "{{value}}CustomLayout"
832
+ },
833
+ {
834
+ visible: "globalControlTypeCustomLayout != 'none'",
835
+ divider: {}
836
+ },
837
+ {
838
+ visible: "globalControlTypeCustomLayout != 'none'",
839
+ globalControl: "Position"
840
+ },
841
+ {
842
+ visible: "globalControlTypeCustomLayout != 'none'",
843
+ globalControl: "ZIndex"
844
+ }
845
+ ];
846
+
847
+ export default CustomLayout;
848
+ ```
849
+
850
+ ---
851
+
852
+ ## Adding New Properties
853
+
854
+ ### Step 1: Create the Property File
855
+
856
+ ```javascript
857
+ // properties/CustomSizes.js
858
+
859
+ const CustomSizes = {
860
+ default: "md",
861
+ items: [
862
+ { value: "xs", title: "Extra Small" },
863
+ { value: "sm", title: "Small" },
864
+ { value: "md", title: "Medium" },
865
+ { value: "lg", title: "Large" },
866
+ { value: "xl", title: "Extra Large" },
867
+ ]
868
+ };
869
+
870
+ export default CustomSizes;
871
+ ```
872
+
873
+ ### Step 2: Export from index.js
874
+
875
+ ```javascript
876
+ // properties/index.js
877
+ export { default as CustomSizes } from "./CustomSizes.js";
878
+ ```
879
+
880
+ ### Step 3: Use in Controls
881
+
882
+ ```javascript
883
+ const SizeSelector = {
884
+ title: "Size",
885
+ id: "elementSize",
886
+ select: {
887
+ use: "CustomSizes"
888
+ }
889
+ };
890
+ ```
891
+
892
+ Or use directly in config files:
893
+
894
+ ```json
895
+ {
896
+ "title": "Size",
897
+ "id": "mySize",
898
+ "select": {
899
+ "use": "CustomSizes"
900
+ }
901
+ }
902
+ ```
903
+
904
+ ---
905
+
906
+ ## Adding Shared Hooks
907
+
908
+ ### Step 1: Create the Shared Hook File
909
+
910
+ Create a new file in the appropriate `shared-hooks/` subfolder:
911
+
912
+ ```javascript
913
+ // shared-hooks/effects/customEffect.js
914
+
915
+ /**
916
+ * Generate custom effect classes based on element properties
917
+ * @param {Object} rw - The RapidWeaver element object
918
+ * @returns {string} CSS class string
919
+ */
920
+ function customEffect(rw) {
921
+ const { customEnabled, customIntensity } = rw.props;
922
+
923
+ if (!customEnabled) return '';
924
+
925
+ return classnames([
926
+ 'custom-effect',
927
+ customIntensity && `intensity-${customIntensity}`
928
+ ]).toString();
929
+ }
930
+ ```
931
+
932
+ ### Step 2: Use in Component Hooks
933
+
934
+ Reference the function in any `hooks.source.js`:
935
+
936
+ ```javascript
937
+ // packs/MyPack.elementsdevpack/components/com.example.mycomponent/hooks.source.js
938
+
939
+ function transformHook(rw) {
940
+ // customEffect is available from shared hooks (no import needed)
941
+ const effectClasses = customEffect(rw);
942
+
943
+ return {
944
+ effectClasses
945
+ };
946
+ }
947
+
948
+ exports.transformHook = transformHook;
949
+ ```
950
+
951
+ ### Step 3: Build
952
+
953
+ ```bash
954
+ npm run build:hooks
955
+ ```
956
+
957
+ ### Naming Conventions
958
+
959
+ - **Folder organization**: Place files in the appropriate category folder
960
+ - **Prefix with `global`**: For element property processing functions (e.g., `globalSpacing`)
961
+ - **Use descriptive names**: Match the function name to the file name
962
+
963
+ | Category | Folder | Example |
964
+ |----------|--------|---------|
965
+ | Core utilities | `core/` | `classnames.js`, `getHoverPrefix.js` |
966
+ | Layout functions | `layout/` | `globalLayout.js` |
967
+ | Visual effects | `effects/` | `globalEffects.js` |
968
+ | Typography | `typography/` | `globalHeadingColor.js` |
969
+
970
+ ### Dead Code Elimination
971
+
972
+ The build system automatically removes unused code. If you add a function to shared hooks but no component uses it, it won't appear in any output `hooks.js` file. This keeps the output lean.
973
+
974
+ ### Example: Complex Shared Hook
975
+
976
+ ```javascript
977
+ // shared-hooks/layout/globalLayout.js
978
+
979
+ /**
980
+ * Generate layout-related CSS classes
981
+ */
982
+ const globalLayout = (app, args = {}) => {
983
+ const {
984
+ globalLayoutPosition: position,
985
+ globalLayoutZIndex: zIndex,
986
+ globalLayoutOverflow: overflow,
987
+ } = app.props;
988
+
989
+ return classnames([
990
+ position,
991
+ zIndex,
992
+ overflow,
993
+ ]).toString();
994
+ };
995
+ ```
996
+
997
+ ---
998
+
999
+ ## Advanced Features
1000
+
1001
+ ### Conditional Visibility
1002
+
1003
+ Show/hide controls based on other property values:
1004
+
1005
+ ```json
1006
+ {
1007
+ "title": "Custom Value",
1008
+ "id": "customValue",
1009
+ "visible": "sizeType == 'custom'",
1010
+ "number": {
1011
+ "default": 100
1012
+ }
1013
+ }
1014
+ ```
1015
+
1016
+ Complex conditions:
1017
+
1018
+ ```json
1019
+ {
1020
+ "visible": "enableFeature == true && mode == 'advanced'"
1021
+ }
1022
+ ```
1023
+
1024
+ ### Format Strings
1025
+
1026
+ Generate CSS class names from values:
1027
+
1028
+ ```json
1029
+ {
1030
+ "id": "gapX",
1031
+ "format": "gap-x-{{value}}",
1032
+ "themeSpacing": {
1033
+ "default": { "base": { "value": "4" } }
1034
+ }
1035
+ }
1036
+ ```
1037
+
1038
+ Output when value is "8": `gap-x-8`
1039
+
1040
+ ### Responsive Controls
1041
+
1042
+ By default, controls are responsive. Disable with:
1043
+
1044
+ ```json
1045
+ {
1046
+ "id": "staticValue",
1047
+ "responsive": false,
1048
+ "text": { "default": "" }
1049
+ }
1050
+ ```
1051
+
1052
+ ### The Advanced Group
1053
+
1054
+ The build system automatically:
1055
+ 1. Injects `CSSClasses` and `ID` controls at the start of the Advanced group
1056
+ 2. Creates an Advanced group if one doesn't exist
1057
+ 3. Moves any existing Advanced group to the end
1058
+ 4. Sets the icon to "gearshape"
1059
+
1060
+ To add controls to the Advanced group:
1061
+
1062
+ ```json
1063
+ {
1064
+ "groups": [
1065
+ {
1066
+ "title": "Advanced",
1067
+ "properties": [
1068
+ { "divider": {} },
1069
+ { "globalControl": "HTMLTag" }
1070
+ ]
1071
+ }
1072
+ ]
1073
+ }
1074
+ ```
1075
+
1076
+ ---
1077
+
1078
+ ## Build Commands
1079
+
1080
+ ### Using the CLI (recommended)
1081
+
1082
+ ```bash
1083
+ # Build everything (properties + hooks)
1084
+ rw-build all
1085
+
1086
+ # Build properties only
1087
+ rw-build properties
1088
+
1089
+ # Build hooks only
1090
+ rw-build hooks
1091
+
1092
+ # Watch for changes
1093
+ rw-build all --watch # Watch both properties and hooks
1094
+ rw-build properties --watch # Watch properties only
1095
+ rw-build hooks --watch # Watch hooks only
1096
+
1097
+ # Build with custom packs directory
1098
+ rw-build all --packs ./my-elements
1099
+
1100
+ # Show help
1101
+ rw-build --help
1102
+ ```
1103
+
1104
+ ### Using npm scripts
1105
+
1106
+ Add these to your `package.json`:
1107
+
1108
+ ```json
1109
+ {
1110
+ "scripts": {
1111
+ "build": "rw-build all",
1112
+ "build:properties": "rw-build properties",
1113
+ "build:hooks": "rw-build hooks",
1114
+ "dev": "rw-build all --watch"
1115
+ }
1116
+ }
1117
+ ```
1118
+
1119
+ Then run:
1120
+
1121
+ ```bash
1122
+ npm run build
1123
+ npm run dev
1124
+ ```
1125
+
1126
+ ### Development Mode Details
1127
+
1128
+ The `--watch` flag monitors for changes and automatically rebuilds:
1129
+
1130
+ | Command | Watches |
1131
+ |---------|---------|
1132
+ | `rw-build all --watch` | Both properties and hooks (runs watchers concurrently) |
1133
+ | `rw-build properties --watch` | `properties.config.json` files in `packs/` |
1134
+ | `rw-build hooks --watch` | `hooks.source.js` files in `packs/` and `shared-hooks/*.js` |
1135
+
1136
+ ### Troubleshooting
1137
+
1138
+ **"Global control 'X' not found"**
1139
+ - Check the control is exported in `controls/index.js`
1140
+ - Verify the spelling matches exactly (case-sensitive)
1141
+
1142
+ **"Property 'X' not found in Properties"**
1143
+ - Check the property is exported in `properties/index.js`
1144
+ - Verify the `use` key spelling
1145
+
1146
+ **Build produces unexpected output**
1147
+ - Check for circular `globalControl` references
1148
+ - Verify JSON syntax in config files
1149
+ - Run with `--trace-warnings` flag for more details
1150
+
1151
+ ---
1152
+
1153
+ ## Example: Complete Element Config
1154
+
1155
+ ```json
1156
+ {
1157
+ "groups": [
1158
+ {
1159
+ "title": "Content",
1160
+ "icon": "text.alignleft",
1161
+ "properties": [
1162
+ {
1163
+ "title": "Heading",
1164
+ "id": "headingText",
1165
+ "text": {
1166
+ "default": "Welcome"
1167
+ }
1168
+ },
1169
+ {
1170
+ "globalControl": "HeadingColor"
1171
+ }
1172
+ ]
1173
+ },
1174
+ {
1175
+ "title": "Layout",
1176
+ "icon": "square.split.bottomrightquarter",
1177
+ "properties": [
1178
+ {
1179
+ "globalControl": "Layout"
1180
+ }
1181
+ ]
1182
+ },
1183
+ {
1184
+ "title": "Spacing",
1185
+ "icon": "squareshape.squareshape.dotted",
1186
+ "properties": [
1187
+ {
1188
+ "globalControl": "Spacing"
1189
+ }
1190
+ ]
1191
+ },
1192
+ {
1193
+ "title": "Background",
1194
+ "icon": "paintbrush.fill",
1195
+ "properties": [
1196
+ {
1197
+ "globalControl": "BackgroundTransparent"
1198
+ }
1199
+ ]
1200
+ },
1201
+ {
1202
+ "title": "Borders",
1203
+ "icon": "square.dashed",
1204
+ "properties": [
1205
+ {
1206
+ "globalControl": "Borders"
1207
+ }
1208
+ ]
1209
+ },
1210
+ {
1211
+ "title": "Advanced",
1212
+ "properties": [
1213
+ {
1214
+ "divider": {}
1215
+ },
1216
+ {
1217
+ "globalControl": "HTMLTag"
1218
+ }
1219
+ ]
1220
+ }
1221
+ ]
1222
+ }
1223
+ ```
1224
+
1225
+ ---
1226
+
1227
+ ## Programmatic Usage
1228
+
1229
+ You can also use rw-elements-tools programmatically in your own build scripts:
1230
+
1231
+ ```javascript
1232
+ import {
1233
+ buildProperties,
1234
+ buildHooks,
1235
+ watchProperties,
1236
+ watchHooks,
1237
+ resolveConfig,
1238
+ Controls,
1239
+ Properties
1240
+ } from 'rw-elements-tools';
1241
+
1242
+ // Resolve configuration from all sources
1243
+ const config = await resolveConfig({
1244
+ packs: './my-elements' // Optional CLI override
1245
+ });
1246
+
1247
+ // Build properties
1248
+ await buildProperties(config);
1249
+
1250
+ // Build hooks
1251
+ await buildHooks(config);
1252
+
1253
+ // Watch for changes
1254
+ await watchProperties(config); // Watch properties only
1255
+ await watchHooks(config); // Watch hooks only
1256
+
1257
+ // Or watch both concurrently
1258
+ await Promise.all([
1259
+ watchProperties(config),
1260
+ watchHooks(config)
1261
+ ]);
1262
+ ```
1263
+
1264
+ ### Accessing Controls and Properties
1265
+
1266
+ ```javascript
1267
+ import { Controls, Properties } from 'rw-elements-tools';
1268
+
1269
+ // Use a control definition
1270
+ console.log(Controls.Spacing);
1271
+ console.log(Controls.BorderRadius);
1272
+
1273
+ // Use a property definition
1274
+ console.log(Properties.FontWeight);
1275
+ console.log(Properties.Slider);
1276
+ ```
1277
+
1278
+ ### Custom Build Pipeline
1279
+
1280
+ ```javascript
1281
+ import { resolveConfig, buildProperties, buildHooks } from 'rw-elements-tools';
1282
+
1283
+ async function customBuild() {
1284
+ const config = await resolveConfig();
1285
+
1286
+ console.log('Building for:', config.packsDir);
1287
+
1288
+ // Build properties first
1289
+ await buildProperties(config);
1290
+
1291
+ // Then build hooks
1292
+ await buildHooks(config);
1293
+
1294
+ console.log('Build complete!');
1295
+ }
1296
+
1297
+ customBuild();
1298
+ ```
1299
+
1300
+ ---
1301
+
1302
+ ## Publishing
1303
+
1304
+ To publish the package to npm:
1305
+
1306
+ ```bash
1307
+ cd src
1308
+ npm login
1309
+ npm publish
1310
+ ```
1311
+
1312
+ For scoped packages:
1313
+
1314
+ ```bash
1315
+ npm publish --access public
1316
+ ```
1317
+
1318
+ ---
1319
+
1320
+ ## Contributing
1321
+
1322
+ When adding new controls or properties:
1323
+
1324
+ 1. **Follow naming conventions**: PascalCase for exports, descriptive names
1325
+ 2. **Place in correct directory**: Use the categorical structure
1326
+ 3. **Add exports**: Update the relevant `index.js`
1327
+ 4. **Test the build**: Run `npm run build` and verify output
1328
+ 5. **Document**: Add comments for complex controls
1329
+
1330
+ ---
1331
+
1332
+ *Last updated: January 2026*
1333
+