@ruebenfox/liquefaction 1.0.6 → 2.0.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 (54) hide show
  1. package/README.md +113 -0
  2. package/bin/cli.js +112 -1
  3. package/components/lib-button/lib-button.css +1 -0
  4. package/components/lib-button/lib-button.js +2 -0
  5. package/components/lib-button/lib-button.liquid +14 -0
  6. package/components/lib-button/manifest.json +45 -0
  7. package/components/lib-clicker/lib-clicker.css +11 -0
  8. package/components/lib-clicker/lib-clicker.js +8 -0
  9. package/components/lib-clicker/lib-clicker.liquid +30 -0
  10. package/components/lib-clicker/manifest.json +69 -0
  11. package/components/lib-footer/lib-footer.css +1 -0
  12. package/components/lib-footer/lib-footer.js +2 -0
  13. package/components/lib-footer/lib-footer.liquid +1 -0
  14. package/components/lib-footer/manifest.json +37 -0
  15. package/components/lib-foxiness/lib-foxiness.css +1 -0
  16. package/components/lib-foxiness/lib-foxiness.js +60 -0
  17. package/components/lib-foxiness/manifest.json +59 -0
  18. package/components/lib-foxy/lib-foxy.css +11 -0
  19. package/components/lib-foxy/lib-foxy.js +8 -0
  20. package/components/lib-foxy/lib-foxy.liquid +45 -0
  21. package/components/lib-foxy/manifest.json +70 -0
  22. package/components/lib-foxy-socks/lib-foxy-socks.css +11 -0
  23. package/components/lib-foxy-socks/lib-foxy-socks.js +8 -0
  24. package/components/lib-foxy-socks/lib-foxy-socks.liquid +21 -0
  25. package/components/lib-foxy-socks/manifest.json +37 -0
  26. package/components/lib-grapes/lib-grapes.css +3 -0
  27. package/components/lib-grapes/lib-grapes.js +42 -0
  28. package/components/lib-grapes/manifest.json +35 -0
  29. package/components/lib-header/lib-header.js +2 -0
  30. package/components/lib-header/lib-header.liquid +1 -0
  31. package/components/lib-header/manifest.json +31 -0
  32. package/components/lib-jam/lib-jam.css +1 -0
  33. package/components/lib-jam/lib-jam.js +8 -0
  34. package/components/lib-jam/lib-jam.liquid +28 -0
  35. package/components/lib-jam/manifest.json +48 -0
  36. package/components/lib-javascript/lib-javascript.js +60 -0
  37. package/components/lib-javascript/manifest.json +28 -0
  38. package/components/lib-ruben/lib-ruben.css +11 -0
  39. package/components/lib-ruben/lib-ruben.js +8 -0
  40. package/components/lib-ruben/lib-ruben.liquid +36 -0
  41. package/components/lib-ruben/manifest.json +85 -0
  42. package/components/lib-slider/lib-slider.css +11 -0
  43. package/components/lib-slider/lib-slider.js +8 -0
  44. package/components/lib-slider/lib-slider.liquid +21 -0
  45. package/components/lib-slider/manifest.json +37 -0
  46. package/components/lib-twinkle-toes/lib-twinkle-toes.css +11 -0
  47. package/components/lib-twinkle-toes/lib-twinkle-toes.js +8 -0
  48. package/components/lib-twinkle-toes/lib-twinkle-toes.liquid +31 -0
  49. package/components/lib-twinkle-toes/manifest.json +77 -0
  50. package/package.json +17 -6
  51. package/registry.json +476 -21
  52. package/components/button/lib-button.css +0 -4
  53. package/components/button/lib-button.js +0 -5
  54. package/components/button/lib-button.liquid +0 -23
package/README.md ADDED
@@ -0,0 +1,113 @@
1
+ # Liquid Library CLI Handbook
2
+
3
+ A concise guide to using the Liquid Library CLI for installing and developing UI components.
4
+
5
+ ## Overview
6
+ - **Public command**: `add` — install components from the library into your theme.
7
+ - **Dev-only commands**: available when developing this library locally (if `dev/*` scripts are present). These scaffold components, manage assets, and run build audits.
8
+
9
+ ## Install Components (Public)
10
+ - **Command**: `liq add <name>`
11
+ - **What it does**: Copies the component files from the library `registry.json` into your theme, prefixing filenames with `lib-`.
12
+ - **Example**:
13
+ ```powershell
14
+ liq add lib-button
15
+ ```
16
+
17
+ ## Develop Components (Dev-only)
18
+ These commands are available when running the CLI inside the library repo with dev scripts present.
19
+
20
+ ### Generate
21
+ - **Command**: `liq generate component <name> [-t javascript|liquid]`
22
+ - **Prompts**:
23
+ - Component type (if `-t` not provided): `JavaScript` or `Liquid`
24
+ - Static assets: `JavaScript only`, `CSS only`, `Both`, or `None`
25
+ - **What it does**:
26
+ - Scaffolds files from templates under `components/lib-<name>/`
27
+ - Creates `manifest.json` with initial hash/version
28
+ - Adds an entry to `registry.json`
29
+ - **Example**:
30
+ ```powershell
31
+ liq generate component slider -t liquid
32
+ ```
33
+
34
+ ### Remove
35
+ - **Command**: `liq remove component <name> [-y]`
36
+ - **Flags**:
37
+ - `-y, --yes`: confirm removal without prompt
38
+ - **What it does**: Removes the component scaffolds and updates the registry.
39
+ - **Example**:
40
+ ```powershell
41
+ liq remove component slider -y
42
+ ```
43
+
44
+ ### Build (Audit)
45
+ - **Command**: `liq build`
46
+ - **What it does**:
47
+ - Computes the primary file hash for each component.
48
+ - Compares against `manifest.primary.hash`/`manifest.registry.hash`.
49
+ - Enforces versioning:
50
+ - If hash changed and `manifest.version` > `registry.version`: accepts the bump, writes new hashes, and updates the registry.
51
+ - If hash changed but versions are equal: requires you to bump `manifest.version`.
52
+ - If `manifest.version` is lower than the registry: fails.
53
+ - For Liquid components, on accepted bump: re-extracts `props`, `dependencies`, and `scope`.
54
+ - **Example**:
55
+ ```powershell
56
+ liq build
57
+ ```
58
+
59
+ ### Manifest Utilities
60
+ - **Compute Hash**: `liq manifest-hash [name] [-a]`
61
+ - `-a, --all`: process all components with a manifest
62
+ - Computes and writes `manifest.primary.hash` + `manifest.registry.hash`; syncs registry hash.
63
+ - **Clean Manifests**: `liq manifest-clean [name] [--dry-run]`
64
+ - `--dry-run`: preview changes without writing
65
+ - Removes unused manifest keys (e.g., old audit metadata).
66
+
67
+ ### Asset Management
68
+ - Group command: `liq asset`
69
+ - **Add**: `liq asset add [name] -t css|js`
70
+ - Adds a CSS or JS asset file to a component and syncs manifest/registry `files`.
71
+ - **Remove**: `liq asset remove [name] -t css|js`
72
+ - Removes a CSS or JS asset file and syncs manifest/registry `files`.
73
+
74
+ ## Metadata Extraction (Liquid)
75
+ - **Descriptions**: Author descriptions inline in the first Liquid comment block:
76
+ - `@prop _title: Button label text`
77
+ - `@prop _price: Display price for the product`
78
+ - If a description is missing, it remains empty; downstream tooling can show a placeholder.
79
+ - **Scope**: Annotate scope in the first comment block:
80
+ - `@scope= product, collection` or `- @scope= all`
81
+ - **Required detection**:
82
+ - A prop is **required** when it has **no** `default` filter.
83
+ - If a `default` is present (e.g., `{{ _title | default: 'Hello' }}`), it is **not required** and the default becomes the `placeholder`.
84
+ - **Dependencies**:
85
+ - Extracted from real `{% render 'lib-...' %}` tags **outside** comments.
86
+ - Guidance examples inside comments are ignored.
87
+
88
+ ## Files & Registry
89
+ - **Manifests**: Per-component `components/lib-<name>/manifest.json` is dev-only; it tracks type, version, primary path, hashes, assets, props, dependencies, and scope.
90
+ - **Registry**: Root `registry.json` is the canonical source for consumers (`liq add`). The build audit updates registry version, hash, and metadata on accepted changes.
91
+
92
+ ## Tips
93
+ - Always bump `manifest.version` when changing the primary file to allow `liq build` to accept and sync changes.
94
+ - Keep `@prop` descriptions short and clear; they are used for documentation and tooling.
95
+ - Only real Liquid code contributes to prop/dependency extraction; comment examples are ignored.
96
+
97
+ ## Examples
98
+ ```powershell
99
+ # Add to theme
100
+ liq add lib-button
101
+
102
+ # Generate a Liquid component with CSS & JS prompts
103
+ liq generate component gallery -t liquid
104
+
105
+ # Audit and sync after edits (remember to bump version)
106
+ liq build
107
+
108
+ # Compute hashes for all manifests
109
+ liq manifest-hash -a
110
+
111
+ # Add a CSS asset to a component
112
+ liq asset add lib-gallery -t css
113
+ ```
package/bin/cli.js CHANGED
@@ -1,6 +1,45 @@
1
1
  #!/usr/bin/env node
2
- const { program } = require('commander');
2
+ const { program, Command } = require('commander');
3
3
  const addAction = require('../src/commands/add');
4
+ let generateComponentAction = null;
5
+ let removeComponentAction = null;
6
+ let buildAction = null;
7
+ let manifestHashAction = null;
8
+ let manifestCleanAction = null;
9
+ let assetAddAction = null;
10
+ let assetRemoveAction = null;
11
+ let serveAction = null;
12
+
13
+ try {
14
+ serveAction = require('../dev/serve');
15
+ } catch (_) {};
16
+
17
+ try {
18
+ generateComponentAction = require('../dev/generate');
19
+ } catch (_) {};
20
+
21
+ try {
22
+ removeComponentAction = require('../dev/remove');
23
+ } catch (_) {};
24
+
25
+ try {
26
+ buildAction = require('../dev/build');
27
+ } catch (_) {};
28
+
29
+ try {
30
+ manifestHashAction = require('../dev/manifest-hash');
31
+ } catch (_) {};
32
+
33
+ try {
34
+ manifestCleanAction = require('../dev/manifest-clean');
35
+ } catch (_) {};
36
+
37
+ try {
38
+ assetAddAction = require('../dev/asset-add');
39
+ } catch(_) {};
40
+ try {
41
+ assetRemoveAction = require('../dev/asset-remove');
42
+ } catch(_) {};
4
43
 
5
44
  program
6
45
  .version('1.0.0')
@@ -11,4 +50,76 @@ program
11
50
  .description('Install a component from the library')
12
51
  .action(addAction);
13
52
 
53
+ if(assetAddAction || assetRemoveAction) {
54
+ const assetCmd = new Command('asset');
55
+ assetCmd.description("Manage asset files on components");
56
+ if (assetAddAction) {
57
+ assetCmd
58
+ .command('add [name]')
59
+ .description('Add asset files (CSS/JS) to an existing component')
60
+ .option('-t, --type <type>', 'Asset type (css|js)')
61
+ .action((name, options) => assetAddAction(name, options));
62
+ }
63
+ if (assetRemoveAction) {
64
+ assetCmd
65
+ .command('remove [name]')
66
+ .description('Remove asset files (CSS/JS) from an existing component')
67
+ .option('-t, --type <type>', 'Asset type (css|js)')
68
+ .action((name, options) => assetRemoveAction(name, options));
69
+ }
70
+ program.addCommand(assetCmd);
71
+ };
72
+
73
+ if(generateComponentAction) {
74
+ const generateCmd = new Command('generate');
75
+ generateCmd.description('Generate scaffolds');
76
+ generateCmd
77
+ .command('component <name>')
78
+ .description('Generate a new component')
79
+ .option('-t, --type <type>', 'Component type (javascript|liquid)')
80
+ .action((name, options) => generateComponentAction(name, options));
81
+ program.addCommand(generateCmd);
82
+ };
83
+
84
+ if(removeComponentAction) {
85
+ const removeCmd = new Command('remove');
86
+ removeCmd.description('Remove scaffolds');
87
+ removeCmd
88
+ .command('component <name>')
89
+ .description('Remove an existing component')
90
+ .option('-y, --yes', 'Confirm removal without prompt')
91
+ .action((name, options) => removeComponentAction(name, options));
92
+ program.addCommand(removeCmd);
93
+ };
94
+
95
+ if(buildAction) {
96
+ program
97
+ .command('build')
98
+ .description('Audit components and sync registry hashes')
99
+ .action(() => buildAction());
100
+ };
101
+
102
+ if(manifestHashAction) {
103
+ program
104
+ .command('manifest-hash [name]')
105
+ .description('Compute and write manifest + registry hash for a component')
106
+ .option('-a, --all', 'Process all components with a manifest')
107
+ .action((name, options) => manifestHashAction(name, options));
108
+ };
109
+
110
+ if(manifestCleanAction) {
111
+ program
112
+ .command('manifest-clean [name]')
113
+ .description('Remove unused keys from component manifest(s)')
114
+ .option('--dry-run', 'Preview changes without writing')
115
+ .action((name, options) => manifestCleanAction(name, options));
116
+ };
117
+
118
+ if(serveAction) {
119
+ program
120
+ .command('serve [components] [context]')
121
+ .description('Start the local dev server for component preview')
122
+ .action((components, context) => serveAction(components, context));
123
+ };
124
+
14
125
  program.parse(process.argv);
@@ -0,0 +1 @@
1
+ /* lib-button.css */
@@ -0,0 +1,2 @@
1
+ // lib-button.js
2
+ // TODO: add boilerplate for Liquid component behavior
@@ -0,0 +1,14 @@
1
+ {% comment %}
2
+ lib-button.liquid
3
+
4
+ Props can be drawn from anythign with the _ prefix:
5
+ {% endcomment %}
6
+
7
+ <button
8
+ id="{{ _button_id }}"
9
+ class="{{ _button_class }}"
10
+ type="{{ _button_type }}">
11
+ <span>
12
+ {{ _button_text }}
13
+ </span>
14
+ </button>
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "lib-button",
3
+ "type": "snippet-component",
4
+ "version": "0.0.5",
5
+ "description": "liquid component scaffold",
6
+ "primary": {
7
+ "path": "lib-button.liquid",
8
+ "hash": "20d21a698c954f5d613f96bcda12a9e8"
9
+ },
10
+ "files": [
11
+ {
12
+ "src": "components/lib-button.css",
13
+ "destDir": "assets"
14
+ },
15
+ {
16
+ "src": "components/lib-button.liquid",
17
+ "destDir": "snippets"
18
+ }
19
+ ],
20
+ "assets": {
21
+ "css": [
22
+ "lib-button.css"
23
+ ],
24
+ "js": [
25
+ "lib-button.js"
26
+ ]
27
+ },
28
+ "props": [
29
+ {
30
+ "name": "_button_text",
31
+ "type": "string",
32
+ "required": false,
33
+ "description": ""
34
+ }
35
+ ],
36
+ "dependencies": [],
37
+ "registry": {
38
+ "createdAt": "2026-01-19T22:51:34.014Z",
39
+ "hash": "20d21a698c954f5d613f96bcda12a9e8"
40
+ },
41
+ "build": {
42
+ "lastAuditAt": "2026-01-25T17:59:55.937Z"
43
+ },
44
+ "scope": []
45
+ }
@@ -0,0 +1,11 @@
1
+ /* lib-clicker.css */
2
+ .lib-clicker {
3
+ --lib-clicker-gap: 0.5rem;
4
+ display: block;
5
+ }
6
+
7
+ .lib-clicker__content {
8
+ margin-block: var(--lib-clicker-gap);
9
+ }
10
+
11
+ .lib-clicker__content--empty { opacity: 0.6; }
@@ -0,0 +1,8 @@
1
+ // lib-lib-clicker.js (optional behavior for Liquid components)
2
+ (() => {
3
+ const selector = '.lib-clicker[data-lib="clicker"]';
4
+ document.querySelectorAll(selector).forEach((el) => {
5
+ // Hook point for interactive behavior
6
+ // Example: el.addEventListener('click', () => {});
7
+ });
8
+ })();
@@ -0,0 +1,30 @@
1
+ {%- comment -%}
2
+ Component: lib-clicker
3
+ Type: snippet-component
4
+
5
+ Props (snake_case with leading underscore). Use a default filter to mark required:
6
+ - _clicker_content: string (required)
7
+ - _aria_label: string (optional)
8
+ - _clicker_id: string (optional)
9
+
10
+ Description
11
+ - @description: Dummy add to cart button.
12
+
13
+ Scope (theme contexts):
14
+ - @scope= product, collection
15
+
16
+ Docs (inline prop descriptions):
17
+ - @prop _content: Product title to display
18
+ - @prop _classes: Additional classes to add to the component wrapper
19
+ - @prop _button_id: Optional ID for the button
20
+ {%- endcomment -%}
21
+
22
+ {% assign _classes = _classes | default: 'bg-red-600 p-3 rounded' %}
23
+ {% assign _button_id = _button_id %}
24
+ {% assign _content = _content | default: product.title %}
25
+
26
+ <button {% if _button_id %} id="{{ _button_id }}" {% endif %} class="{{ _classes }}">
27
+ <span id="test-one" class="lib-clicker">
28
+ {{ _content }}
29
+ </span>
30
+ </button>
@@ -0,0 +1,69 @@
1
+ {
2
+ "name": "lib-clicker",
3
+ "type": "snippet-component",
4
+ "version": "0.1.0",
5
+ "description": "Dummy add to cart button.",
6
+ "primary": {
7
+ "path": "lib-clicker.liquid",
8
+ "hash": "99b32b4f5482111e958ff7be9dde9446"
9
+ },
10
+ "files": [
11
+ {
12
+ "src": "components/lib-clicker/lib-clicker.css",
13
+ "destDir": "assets",
14
+ "hash": "1400e68714456397b1b08bfd62997c23"
15
+ },
16
+ {
17
+ "src": "components/lib-clicker/lib-clicker.liquid",
18
+ "destDir": "snippets",
19
+ "hash": "99b32b4f5482111e958ff7be9dde9446"
20
+ },
21
+ {
22
+ "src": "components/lib-clicker/lib-clicker.js",
23
+ "destDir": "assets",
24
+ "hash": "4c226a2521a6bdccc1020348c7d320a7"
25
+ }
26
+ ],
27
+ "assets": {
28
+ "css": [
29
+ "lib-clicker.css"
30
+ ],
31
+ "js": [
32
+ "lib-clicker.js"
33
+ ]
34
+ },
35
+ "props": [
36
+ {
37
+ "name": "_content",
38
+ "type": "string",
39
+ "required": true,
40
+ "description": "Product title to display",
41
+ "placeholder": "product.title"
42
+ },
43
+ {
44
+ "name": "_classes",
45
+ "type": "string",
46
+ "required": true,
47
+ "description": "Additional classes to add to the component wrapper",
48
+ "placeholder": "'bg-red-600 p-3 rounded'"
49
+ },
50
+ {
51
+ "name": "_button_id",
52
+ "type": "string",
53
+ "required": false,
54
+ "description": "Optional ID for the button"
55
+ }
56
+ ],
57
+ "dependencies": [],
58
+ "scope": [
59
+ "product",
60
+ "collection"
61
+ ],
62
+ "registry": {
63
+ "createdAt": "2026-01-31T00:26:37.644Z",
64
+ "hash": "99b32b4f5482111e958ff7be9dde9446"
65
+ },
66
+ "build": {
67
+ "lastAuditAt": "2026-01-31T00:27:20.182Z"
68
+ }
69
+ }
@@ -0,0 +1 @@
1
+ /* lib-footer.css */
@@ -0,0 +1,2 @@
1
+ // lib-footer.js
2
+ // TODO: add boilerplate for Liquid component behavior
@@ -0,0 +1 @@
1
+ {% comment %} lib-footer.liquid {% endcomment %}
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "lib-footer",
3
+ "type": "snippet-component",
4
+ "version": "0.0.1",
5
+ "description": "liquid component scaffold",
6
+ "primary": {
7
+ "path": "lib-footer.liquid",
8
+ "hash": "6ec74860565455844b1f3c46a28f4bad"
9
+ },
10
+ "files": [
11
+ {
12
+ "src": "components/lib-footer.css",
13
+ "destDir": "assets"
14
+ },
15
+ {
16
+ "src": "components/lib-footer.liquid",
17
+ "destDir": "snippets"
18
+ }
19
+ ],
20
+ "assets": {
21
+ "css": [
22
+ "lib-footer.css"
23
+ ],
24
+ "js": [
25
+ "lib-footer.js"
26
+ ]
27
+ },
28
+ "props": [],
29
+ "dependencies": [],
30
+ "registry": {
31
+ "createdAt": "2026-01-19T23:15:09.156Z",
32
+ "hash": "6ec74860565455844b1f3c46a28f4bad"
33
+ },
34
+ "build": {
35
+ "lastAuditAt": ""
36
+ }
37
+ }
@@ -0,0 +1 @@
1
+ /* lib-foxiness.css */
@@ -0,0 +1,60 @@
1
+ /**
2
+ * @scope: global
3
+ * @docs: This is to test data extraction for WP's.
4
+ * @dependencies: [lib-helpers, lib-widgets]
5
+ */
6
+
7
+ // lib-lib-foxiness.js (Light DOM)
8
+ export class LibFoxiness extends HTMLElement {
9
+ static get is() { return 'lib-foxiness'; }
10
+
11
+ // These are the "Props" your Registry/In-situ docs will scrape
12
+ static get props() {
13
+ return {
14
+ 'aria-label': 'string',
15
+ 'theme': 'primary | secondary',
16
+ 'disabled': 'boolean'
17
+ };
18
+ };
19
+
20
+ static get observedAttributes() {
21
+ return Object.keys(LibFoxiness.props);
22
+ };
23
+
24
+ connectedCallback() {
25
+
26
+ if(this._initialized) return;
27
+ this._initialized = true;
28
+ this.classList.add('lib-foxiness');
29
+
30
+ // Initial attribute check
31
+ if(!this.hasAttribute('aria-label')) {
32
+ this.setAttribute('aria-label', 'Lib LibFoxiness');
33
+ };
34
+
35
+ // "Lego" Root Construction
36
+ let root = this.querySelector('.lib-foxiness__root');
37
+ if(!root) {
38
+ root = document.createElement('div');
39
+ root.className = 'lib-foxiness__root';
40
+ root.setAttribute('role', 'region');
41
+ const slot = document.createElement('slot');
42
+ root.appendChild(slot);
43
+ this.appendChild(root);
44
+ };
45
+
46
+ };
47
+
48
+ attributeChangedCallback(name, _oldVal, newVal) {
49
+ const root = this.querySelector('.lib-foxiness__root');
50
+ if(root && name === 'aria-label') {
51
+ root.setAttribute('aria-label', newVal || '');
52
+ };
53
+ };
54
+
55
+ };
56
+
57
+ // Safe Registry Handshake
58
+ if(!customElements.get(LibFoxiness.is)) {
59
+ customElements.define(LibFoxiness.is, LibFoxiness);
60
+ };
@@ -0,0 +1,59 @@
1
+ {
2
+ "name": "lib-foxiness",
3
+ "type": "web-component",
4
+ "version": "0.1.1",
5
+ "description": "This is to test data extraction for WP's.",
6
+ "primary": {
7
+ "path": "lib-foxiness.js",
8
+ "hash": "ccc89652ee3cf755b831d0242e0830b6"
9
+ },
10
+ "files": [
11
+ {
12
+ "src": "components/lib-foxiness/lib-foxiness.js",
13
+ "destDir": "assets"
14
+ },
15
+ {
16
+ "src": "components/lib-foxiness/lib-foxiness.css",
17
+ "destDir": "assets"
18
+ }
19
+ ],
20
+ "assets": {
21
+ "css": [
22
+ "lib-foxiness.css"
23
+ ]
24
+ },
25
+ "props": [
26
+ {
27
+ "name": "aria-label",
28
+ "type": "string",
29
+ "required": false,
30
+ "description": ""
31
+ },
32
+ {
33
+ "name": "theme",
34
+ "type": "primary | secondary",
35
+ "required": false,
36
+ "description": ""
37
+ },
38
+ {
39
+ "name": "disabled",
40
+ "type": "boolean",
41
+ "required": false,
42
+ "description": ""
43
+ }
44
+ ],
45
+ "dependencies": [
46
+ "lib-helpers",
47
+ "lib-widgets"
48
+ ],
49
+ "scope": [
50
+ "global"
51
+ ],
52
+ "registry": {
53
+ "createdAt": "2026-01-29T23:08:38.154Z",
54
+ "hash": "ccc89652ee3cf755b831d0242e0830b6"
55
+ },
56
+ "build": {
57
+ "lastAuditAt": "2026-01-30T23:12:46.892Z"
58
+ }
59
+ }
@@ -0,0 +1,11 @@
1
+ /* lib-foxy.css */
2
+ .lib-foxy {
3
+ --lib-foxy-gap: 0.5rem;
4
+ display: block;
5
+ }
6
+
7
+ .lib-foxy__content {
8
+ margin-block: var(--lib-foxy-gap);
9
+ }
10
+
11
+ .lib-foxy__content--empty { opacity: 0.6; }
@@ -0,0 +1,8 @@
1
+ // lib-lib-foxy.js (optional behavior for Liquid components)
2
+ (() => {
3
+ const selector = '.lib-foxy[data-lib="foxy"]';
4
+ document.querySelectorAll(selector).forEach((el) => {
5
+ // Hook point for interactive behavior
6
+ // Example: el.addEventListener('click', () => {});
7
+ });
8
+ })();
@@ -0,0 +1,45 @@
1
+ {%- comment -%}
2
+ Component: lib-foxy
3
+ Type: snippet-component
4
+
5
+ Props (snake_case with leading underscore):
6
+ - _foxy_content: string (required)
7
+ - _aria_label: string (optional)
8
+ - _foxy_id: string (optional)
9
+
10
+ Dependencies (rendered children):
11
+ - {% render 'lib-child', _child_content: '...' %}
12
+
13
+ Scope (theme contexts):
14
+ - @scope= all
15
+
16
+ Docs (inline prop descriptions):
17
+ - @prop _empty: Describe the main content when empty.
18
+ - @prop _test: Test for required flagging.
19
+
20
+ {%- endcomment -%}
21
+
22
+ {% assign _empty = 'Empty' | default: 'Empty' %}
23
+ {% assign _test = 'Test for require flag' %}
24
+ {% assign _agile = 'Test for require flag' | default: 'Test for require flag' %}
25
+ {% assign test = 'Test for ommision in build' %}
26
+
27
+ <div class="lib-foxy" data-lib="foxy" role="region">
28
+ {% render 'lib-button',
29
+ _button_class: "bg-red-600 text-white px-6 py-3 rounded-lg font-medium hover:bg-indigo-700 transition-colors shadow-lg",
30
+ _button_id: "button-id-1",
31
+ _button_text: "Click Me Bitch"
32
+ %}
33
+ {%- if _foxy_content -%}
34
+ <div class="lib-foxy__content">
35
+ {{ _foxy_content }}
36
+ </div>
37
+ {%- else -%}
38
+ <div class="lib-foxy__content lib-foxy__content--empty" aria-hidden="true">
39
+ {{ _empty }}
40
+ </div>
41
+ {%- endif -%}
42
+ {% render 'lib-footer',
43
+ _footer_text: 'This is the footer text'
44
+ %}
45
+ </div>