@sociallane/elements 1.0.12 → 1.0.14

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.
@@ -0,0 +1,58 @@
1
+ name: SocialLane npm/npx Gates
2
+
3
+ on:
4
+ pull_request:
5
+ paths:
6
+ - 'sociallane-elements/**'
7
+ push:
8
+ branches:
9
+ - main
10
+ paths:
11
+ - 'sociallane-elements/**'
12
+ workflow_dispatch:
13
+
14
+ jobs:
15
+ cli-smoke:
16
+ runs-on: ubuntu-latest
17
+ defaults:
18
+ run:
19
+ working-directory: sociallane-elements
20
+ steps:
21
+ - name: Checkout
22
+ uses: actions/checkout@v4
23
+
24
+ - name: Setup Node
25
+ uses: actions/setup-node@v4
26
+ with:
27
+ node-version: '20'
28
+
29
+ - name: CLI smoke tests
30
+ run: node scripts/test-cli-smoke.js
31
+
32
+ - name: List command sanity check
33
+ run: node scripts/install.js list --json
34
+
35
+ - name: Doctor command sanity check
36
+ run: node scripts/install.js doctor --json --target .
37
+
38
+ release-gate:
39
+ if: github.event_name == 'workflow_dispatch'
40
+ runs-on: ubuntu-latest
41
+ needs: cli-smoke
42
+ defaults:
43
+ run:
44
+ working-directory: sociallane-elements
45
+ steps:
46
+ - name: Checkout
47
+ uses: actions/checkout@v4
48
+
49
+ - name: Setup Node
50
+ uses: actions/setup-node@v4
51
+ with:
52
+ node-version: '20'
53
+
54
+ - name: Sync canonical widget manifest
55
+ run: node scripts/generate-widget-manifest.js
56
+
57
+ - name: Release gate (strict)
58
+ run: node scripts/release-gate.js --strict
@@ -55,13 +55,13 @@ cd wp-content/plugins/sociallane-elements && npm install && npm run build
55
55
 
56
56
  ```bash
57
57
  # From your WordPress root (directory that contains wp-content)
58
- npx @sociallane/elements --minimal
58
+ npx @sociallane/elements --base
59
59
  ```
60
60
 
61
61
  Then add widgets by slug (no manual `widgets.json` editing):
62
62
 
63
63
  ```bash
64
- npx @sociallane/elements add hero-split faq content-block widget-filter
64
+ npx @sociallane/elements add hero-split faq-stacked content-block widget-filter
65
65
  ```
66
66
 
67
67
  Each `add` updates `widgets.json` and runs the build. You can run `add` anytime to add more widgets.
@@ -77,8 +77,8 @@ This copies the full plugin to `wp-content/plugins/sociallane-elements`, runs `n
77
77
  **Custom path:**
78
78
 
79
79
  ```bash
80
- npx @sociallane/elements --minimal path/to/wp-content/plugins/sociallane-elements
81
- npx @sociallane/elements add hero-split faq # run from WordPress root or plugin dir
80
+ npx @sociallane/elements --base path/to/wp-content/plugins/sociallane-elements
81
+ npx @sociallane/elements add --target path/to/wp-content/plugins/sociallane-elements hero-split faq-stacked
82
82
  ```
83
83
 
84
84
  **Single widget (per-widget packages):**
@@ -87,7 +87,7 @@ You can install one widget at a time via its own package. This installs the Soci
87
87
 
88
88
  ```bash
89
89
  # From your WordPress root or wp-content/plugins
90
- npx @sociallane/widget-hero-overlay
90
+ npx @sociallane/widget-content-block
91
91
  npx @sociallane/widget-faq-stacked
92
92
  ```
93
93
 
@@ -7,8 +7,11 @@ Quick reference for loading widgets via npm workspaces.
7
7
  ## One-liners
8
8
 
9
9
  ```bash
10
- # Full install REQUIRED for styled widgets (from plugin root)
11
- npm install && npm run build
10
+ # Base install (no widgets imported yet)
11
+ npx @sociallane/elements --base
12
+
13
+ # Add selected widgets
14
+ npx @sociallane/elements add hero-split faq-stacked content-block
12
15
 
13
16
  # Dev watch (rebuilds on file change)
14
17
  npm run dev
@@ -28,7 +31,7 @@ Edit `widgets.json` at plugin root:
28
31
  "hero-split",
29
32
  "hero-overlay",
30
33
  "content-block",
31
- "faq"
34
+ "faq-stacked"
32
35
  ]
33
36
  }
34
37
  ```
@@ -39,7 +42,10 @@ Only slugs listed here are loaded. Add or remove as needed.
39
42
 
40
43
  ## Widget → npm package & command
41
44
 
42
- Every widget and its npm package / add command:
45
+ Common widgets and their npm package / add command:
46
+
47
+ > Note: per-widget packages may not all be published at the same time.
48
+ > The most reliable flow is `npx @sociallane/elements --base` then `npx @sociallane/elements add ...`.
43
49
 
44
50
  | Widget | Package | Command |
45
51
  |--------|---------|---------|
@@ -52,7 +58,9 @@ Every widget and its npm package / add command:
52
58
  | cta-banner | `@sociallane/widget-cta-banner` | `npm install @sociallane/widget-cta-banner` |
53
59
  | cta-notify | `@sociallane/widget-cta-notify` | `npm install @sociallane/widget-cta-notify` |
54
60
  | cta-split | `@sociallane/widget-cta-split` | `npm install @sociallane/widget-cta-split` |
55
- | faq | `@sociallane/widget-faq` | `npm install @sociallane/widget-faq` |
61
+ | faq-stacked | `@sociallane/widget-faq-stacked` | `npm install @sociallane/widget-faq-stacked` |
62
+ | faq-split | `@sociallane/widget-faq-split` | `npm install @sociallane/widget-faq-split` |
63
+ | faq-centered | `@sociallane/widget-faq-centered` | `npm install @sociallane/widget-faq-centered` |
56
64
  | feature-grid | `@sociallane/widget-feature-grid` | `npm install @sociallane/widget-feature-grid` |
57
65
  | feature-list | `@sociallane/widget-feature-list` | `npm install @sociallane/widget-feature-list` |
58
66
  | feature-list-cta | `@sociallane/widget-feature-list-cta` | `npm install @sociallane/widget-feature-list-cta` |
@@ -62,25 +70,34 @@ Every widget and its npm package / add command:
62
70
  | form-contact | `@sociallane/widget-form-contact` | `npm install @sociallane/widget-form-contact` |
63
71
  | grid-case-studies | `@sociallane/widget-grid-case-studies` | `npm install @sociallane/widget-grid-case-studies` |
64
72
  | grid-components | `@sociallane/widget-grid-components` | `npm install @sociallane/widget-grid-components` |
65
- | grid-posts | `@sociallane/widget-grid-posts` | `npm install @sociallane/widget-grid-posts` |
73
+ | posts-grid | `@sociallane/widget-posts-grid` | `npm install @sociallane/widget-posts-grid` |
74
+ | posts-grid-overlay | `@sociallane/widget-posts-grid-overlay` | `npm install @sociallane/widget-posts-grid-overlay` |
66
75
  | grid-team | `@sociallane/widget-grid-team` | `npm install @sociallane/widget-grid-team` |
67
- | grid-testimonials | `@sociallane/widget-grid-testimonials` | `npm install @sociallane/widget-grid-testimonials` |
76
+ | testimonials-grid | `@sociallane/widget-testimonials-grid` | `npm install @sociallane/widget-testimonials-grid` |
77
+ | testimonials-masonry | `@sociallane/widget-testimonials-masonry` | `npm install @sociallane/widget-testimonials-masonry` |
78
+ | testimonials-bento | `@sociallane/widget-testimonials-bento` | `npm install @sociallane/widget-testimonials-bento` |
68
79
  | hero-announcement | `@sociallane/widget-hero-announcement` | `npm install @sociallane/widget-hero-announcement` |
69
80
  | hero-centered-image | `@sociallane/widget-hero-centered-image` | `npm install @sociallane/widget-hero-centered-image` |
70
81
  | hero-collage | `@sociallane/widget-hero-collage` | `npm install @sociallane/widget-hero-collage` |
71
82
  | hero-overlay | `@sociallane/widget-hero-overlay` | `npm install @sociallane/widget-hero-overlay` |
72
- | hero-saas | `@sociallane/widget-hero-saas` | `npm install @sociallane/widget-hero-saas` |
83
+ | hero-saas-split | `@sociallane/widget-hero-saas-split` | `npm install @sociallane/widget-hero-saas-split` |
84
+ | hero-saas-stacked | `@sociallane/widget-hero-saas-stacked` | `npm install @sociallane/widget-hero-saas-stacked` |
85
+ | hero-saas-centered | `@sociallane/widget-hero-saas-centered` | `npm install @sociallane/widget-hero-saas-centered` |
73
86
  | hero-split | `@sociallane/widget-hero-split` | `npm install @sociallane/widget-hero-split` |
74
87
  | hero-stacked-image | `@sociallane/widget-hero-stacked-image` | `npm install @sociallane/widget-hero-stacked-image` |
75
88
  | intro-pattern | `@sociallane/widget-intro-pattern` | `npm install @sociallane/widget-intro-pattern` |
76
89
  | intro-text | `@sociallane/widget-intro-text` | `npm install @sociallane/widget-intro-text` |
77
- | logo-grid | `@sociallane/widget-logo-grid` | `npm install @sociallane/widget-logo-grid` |
90
+ | logo-grid-centered | `@sociallane/widget-logo-grid-centered` | `npm install @sociallane/widget-logo-grid-centered` |
91
+ | logo-grid-row | `@sociallane/widget-logo-grid-row` | `npm install @sociallane/widget-logo-grid-row` |
92
+ | logo-grid-split | `@sociallane/widget-logo-grid-split` | `npm install @sociallane/widget-logo-grid-split` |
78
93
  | nav-default | `@sociallane/widget-nav-default` | `npm install @sociallane/widget-nav-default` |
79
94
  | nav-centered | `@sociallane/widget-nav-centered` | `npm install @sociallane/widget-nav-centered` |
80
95
  | nav-minimal | `@sociallane/widget-nav-minimal` | `npm install @sociallane/widget-nav-minimal` |
81
96
  | nav-compact | `@sociallane/widget-nav-compact` | `npm install @sociallane/widget-nav-compact` |
82
97
  | nav-floating | `@sociallane/widget-nav-floating` | `npm install @sociallane/widget-nav-floating` |
83
98
  | newsletter | `@sociallane/widget-newsletter` | `npm install @sociallane/widget-newsletter` |
99
+ | newsletter-card | `@sociallane/widget-newsletter-card` | `npm install @sociallane/widget-newsletter-card` |
100
+ | newsletter-section | `@sociallane/widget-newsletter-section` | `npm install @sociallane/widget-newsletter-section` |
84
101
  | outreach-dashboard | `@sociallane/widget-outreach-dashboard` | `npm install @sociallane/widget-outreach-dashboard` |
85
102
  | pipeline-dashboard | `@sociallane/widget-pipeline-dashboard` | `npm install @sociallane/widget-pipeline-dashboard` |
86
103
  | pricing-table | `@sociallane/widget-pricing-table` | `npm install @sociallane/widget-pricing-table` |
@@ -89,7 +106,9 @@ Every widget and its npm package / add command:
89
106
  | services | `@sociallane/widget-services` | `npm install @sociallane/widget-services` |
90
107
  | simple-page-hero | `@sociallane/widget-simple-page-hero` | `npm install @sociallane/widget-simple-page-hero` |
91
108
  | social-proof | `@sociallane/widget-social-proof` | `npm install @sociallane/widget-social-proof` |
109
+ | social-proof-trust | `@sociallane/widget-social-proof-trust` | `npm install @sociallane/widget-social-proof-trust` |
92
110
  | testimonial-quote | `@sociallane/widget-testimonial-quote` | `npm install @sociallane/widget-testimonial-quote` |
111
+ | widget-filter | `@sociallane/widget-widget-filter` | `npm install @sociallane/widget-widget-filter` |
93
112
 
94
113
  Then add the slug to `widgets.json`.
95
114
 
@@ -99,12 +118,12 @@ Then add the slug to `widgets.json`.
99
118
 
100
119
  | Category | Slugs |
101
120
  |----------|-------|
102
- | Heroes | `hero-split`, `hero-overlay`, `hero-saas`, `hero-collage`, `hero-centered-image`, `hero-stacked-image`, `hero-announcement`, `simple-page-hero` |
103
- | Content | `content-block`, `intro-text`, `intro-pattern`, `faq`, `feature-list`, `feature-list-cta`, `feature-grid` |
104
- | Cards & Grids | `card-hover-reveal`, `bento-grid`, `bento-portfolio`, `grid-posts`, `grid-team`, `grid-testimonials`, `grid-case-studies`, `grid-components`, `logo-grid`, `client-logos` |
105
- | Forms & CTAs | `cta-banner`, `cta-split`, `cta-notify`, `newsletter`, `form-contact`, `pricing-table` |
121
+ | Heroes | `hero-split`, `hero-overlay`, `hero-overlay-single`, `hero-overlay-slider`, `hero-saas-split`, `hero-saas-stacked`, `hero-saas-centered`, `hero-collage`, `hero-centered-image`, `hero-stacked-image`, `hero-announcement`, `simple-page-hero`, `page-hero-left`, `page-hero-center` |
122
+ | Content | `content-block`, `intro-text`, `intro-pattern`, `faq-stacked`, `faq-split`, `faq-centered`, `feature-list`, `feature-list-cta`, `feature-grid` |
123
+ | Cards & Grids | `card-hover-reveal`, `bento-grid`, `bento-portfolio`, `posts-grid`, `posts-grid-overlay`, `grid-team`, `testimonials-grid`, `testimonials-masonry`, `testimonials-bento`, `grid-case-studies`, `grid-components`, `logo-grid-centered`, `logo-grid-row`, `logo-grid-split`, `client-logos` |
124
+ | Forms & CTAs | `cta-banner`, `cta-split`, `cta-notify`, `newsletter`, `newsletter-card`, `newsletter-section`, `form-contact`, `pricing-table` |
106
125
  | Navigation | `nav-default`, `nav-centered`, `nav-minimal`, `nav-compact`, `nav-floating`, `footer`, `footer-brand`, `footer-links-contact` |
107
- | Other | `section-stats`, `social-proof`, `services`, `blog-grid`, `outreach-dashboard`, `pipeline-dashboard`, `sales-dashboard`, `testimonial-quote` |
126
+ | Other | `section-stats`, `social-proof`, `social-proof-trust`, `services`, `blog-grid`, `outreach-dashboard`, `pipeline-dashboard`, `sales-dashboard`, `testimonial-quote`, `widget-filter` |
108
127
 
109
128
  ---
110
129
 
@@ -29,7 +29,8 @@ Edit `widgets.json` to include only the widget slugs you want. You can also let
29
29
 
30
30
  Adding or removing widget directories is reflected in `widgets.json` automatically:
31
31
 
32
- - **On `npm install`** — The postinstall script runs `sync-widgets` then `build`. Any new folder under `packages/widgets/{slug}` with `{slug}.php` is added to `widgets.json`; removed folders are removed from the list. Existing order is preserved; new slugs are appended sorted.
32
+ - **On `npm install`** — The postinstall script runs `sync-widgets` then `build` by default. Any new folder under `packages/widgets/{slug}` with `{slug}.php` is added to `widgets.json`; removed folders are removed from the list. Existing order is preserved; new slugs are appended sorted.
33
+ The installers use `SOCIALLANE_SKIP_SYNC_WIDGETS=1` for base/cherry-pick flows so `widgets.json` is not expanded unintentionally.
33
34
  - **Manual sync** — From the plugin root run:
34
35
  ```bash
35
36
  npm run sync-widgets
@@ -42,7 +43,7 @@ Adding or removing widget directories is reflected in `widgets.json` automatical
42
43
  "hero-split",
43
44
  "hero-overlay",
44
45
  "content-block",
45
- "faq"
46
+ "faq-stacked"
46
47
  ]
47
48
  }
48
49
  ```
@@ -65,10 +66,10 @@ Use submodules so each WordPress instance only has the core package and the widg
65
66
 
66
67
  # Add only the widgets you want
67
68
  git submodule add <url-to-widget-hero-split> packages/widgets/hero-split
68
- git submodule add <url-to-widget-faq> packages/widgets/faq
69
+ git submodule add <url-to-widget-faq-stacked> packages/widgets/faq-stacked
69
70
  ```
70
71
 
71
- 3. Update **widgets.json** so its `widgets` array lists only the slugs you added (e.g. `hero-split`, `faq`).
72
+ 3. Update **widgets.json** so its `widgets` array lists only the slugs you added (e.g. `hero-split`, `faq-stacked`).
72
73
 
73
74
  4. Install and build from plugin root (both required for styled widgets):
74
75
 
@@ -123,13 +124,13 @@ The plugin is published as `@sociallane/elements`. To publish:
123
124
 
124
125
  ## Per-widget npm packages
125
126
 
126
- Individual widgets are published as `@sociallane/widget-<slug>` (e.g. `@sociallane/widget-hero-overlay`). Run from your WordPress root or `wp-content/plugins`:
127
+ Individual widgets are published as `@sociallane/widget-<slug>` (for example `@sociallane/widget-faq-stacked`). Run from your WordPress root or `wp-content/plugins`:
127
128
 
128
129
  ```bash
129
- npx @sociallane/widget-hero-overlay
130
+ npx @sociallane/widget-faq-stacked
130
131
  ```
131
132
 
132
- The installer installs the base plugin (`@sociallane/elements`) with `--minimal` if it is not present, then copies the widget into the plugin, runs `sync-widgets`, and `npm install`. Use these when you want a one-command install for a single widget. To add multiple widgets, `npx @sociallane/elements add slug1 slug2` is usually simpler.
133
+ The installer installs the base plugin (`@sociallane/elements`) with `--base` if it is not present, then delegates to `npx @sociallane/elements add --target <pluginDir> <slug>`. Use these when you want a one-command install for a single widget. To add multiple widgets, `npx @sociallane/elements add --target <pluginDir> slug1 slug2` is usually simpler.
133
134
 
134
135
  ## Adding a new widget package
135
136
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sociallane/elements",
3
- "version": "1.0.12",
3
+ "version": "1.0.14",
4
4
  "description": "Elementor widgets and elements with Tailwind CSS for SocialLane. WordPress plugin.",
5
5
  "type": "module",
6
6
  "private": false,
@@ -30,8 +30,13 @@
30
30
  "postinstall": "node scripts/postinstall.js",
31
31
  "setup": "bash scripts/setup.sh",
32
32
  "sync-widgets": "node scripts/sync-widgets.js",
33
+ "manifest:widgets": "node scripts/generate-widget-manifest.js",
34
+ "generate:widget-table": "node scripts/generate-widget-table.js",
33
35
  "build:widget-packages": "node scripts/build-widget-packages.js",
34
36
  "publish:widgets": "node scripts/build-widget-packages.js && node scripts/publish-widget-packages.js",
37
+ "test:cli-smoke": "node scripts/test-cli-smoke.js",
38
+ "release:check": "node scripts/release-gate.js --strict",
39
+ "release:check:local": "node scripts/release-gate.js --strict --skip-registry",
35
40
  "reinstall": "rm -rf node_modules && npm install",
36
41
  "format": "prettier --write .",
37
42
  "format:check": "prettier --check ."
@@ -0,0 +1,291 @@
1
+ {
2
+ "schema_version": 1,
3
+ "generated_at": "2026-02-10T09:16:15.290Z",
4
+ "source": "packages/widgets",
5
+ "widgets": [
6
+ {
7
+ "slug": "bento-grid",
8
+ "package": "@sociallane/widget-bento-grid"
9
+ },
10
+ {
11
+ "slug": "bento-grid-4",
12
+ "package": "@sociallane/widget-bento-grid-4"
13
+ },
14
+ {
15
+ "slug": "bento-grid-5",
16
+ "package": "@sociallane/widget-bento-grid-5"
17
+ },
18
+ {
19
+ "slug": "bento-grid-6",
20
+ "package": "@sociallane/widget-bento-grid-6"
21
+ },
22
+ {
23
+ "slug": "bento-portfolio",
24
+ "package": "@sociallane/widget-bento-portfolio"
25
+ },
26
+ {
27
+ "slug": "bento-portfolio-4",
28
+ "package": "@sociallane/widget-bento-portfolio-4"
29
+ },
30
+ {
31
+ "slug": "bento-portfolio-5",
32
+ "package": "@sociallane/widget-bento-portfolio-5"
33
+ },
34
+ {
35
+ "slug": "bento-portfolio-6",
36
+ "package": "@sociallane/widget-bento-portfolio-6"
37
+ },
38
+ {
39
+ "slug": "blog-grid",
40
+ "package": "@sociallane/widget-blog-grid"
41
+ },
42
+ {
43
+ "slug": "card-hover-reveal",
44
+ "package": "@sociallane/widget-card-hover-reveal"
45
+ },
46
+ {
47
+ "slug": "client-logos",
48
+ "package": "@sociallane/widget-client-logos"
49
+ },
50
+ {
51
+ "slug": "content-block",
52
+ "package": "@sociallane/widget-content-block"
53
+ },
54
+ {
55
+ "slug": "cta-banner",
56
+ "package": "@sociallane/widget-cta-banner"
57
+ },
58
+ {
59
+ "slug": "cta-notify",
60
+ "package": "@sociallane/widget-cta-notify"
61
+ },
62
+ {
63
+ "slug": "cta-split",
64
+ "package": "@sociallane/widget-cta-split"
65
+ },
66
+ {
67
+ "slug": "faq-centered",
68
+ "package": "@sociallane/widget-faq-centered"
69
+ },
70
+ {
71
+ "slug": "faq-split",
72
+ "package": "@sociallane/widget-faq-split"
73
+ },
74
+ {
75
+ "slug": "faq-stacked",
76
+ "package": "@sociallane/widget-faq-stacked"
77
+ },
78
+ {
79
+ "slug": "feature-grid",
80
+ "package": "@sociallane/widget-feature-grid"
81
+ },
82
+ {
83
+ "slug": "feature-grid-centered",
84
+ "package": "@sociallane/widget-feature-grid-centered"
85
+ },
86
+ {
87
+ "slug": "feature-list",
88
+ "package": "@sociallane/widget-feature-list"
89
+ },
90
+ {
91
+ "slug": "feature-list-cta",
92
+ "package": "@sociallane/widget-feature-list-cta"
93
+ },
94
+ {
95
+ "slug": "footer",
96
+ "package": "@sociallane/widget-footer"
97
+ },
98
+ {
99
+ "slug": "footer-brand",
100
+ "package": "@sociallane/widget-footer-brand"
101
+ },
102
+ {
103
+ "slug": "footer-links-contact",
104
+ "package": "@sociallane/widget-footer-links-contact"
105
+ },
106
+ {
107
+ "slug": "form-contact",
108
+ "package": "@sociallane/widget-form-contact"
109
+ },
110
+ {
111
+ "slug": "grid-case-studies",
112
+ "package": "@sociallane/widget-grid-case-studies"
113
+ },
114
+ {
115
+ "slug": "grid-components",
116
+ "package": "@sociallane/widget-grid-components"
117
+ },
118
+ {
119
+ "slug": "grid-team",
120
+ "package": "@sociallane/widget-grid-team"
121
+ },
122
+ {
123
+ "slug": "hero-announcement",
124
+ "package": "@sociallane/widget-hero-announcement"
125
+ },
126
+ {
127
+ "slug": "hero-centered-image",
128
+ "package": "@sociallane/widget-hero-centered-image"
129
+ },
130
+ {
131
+ "slug": "hero-collage",
132
+ "package": "@sociallane/widget-hero-collage"
133
+ },
134
+ {
135
+ "slug": "hero-overlay",
136
+ "package": "@sociallane/widget-hero-overlay"
137
+ },
138
+ {
139
+ "slug": "hero-overlay-single",
140
+ "package": "@sociallane/widget-hero-overlay-single"
141
+ },
142
+ {
143
+ "slug": "hero-overlay-slider",
144
+ "package": "@sociallane/widget-hero-overlay-slider"
145
+ },
146
+ {
147
+ "slug": "hero-saas-centered",
148
+ "package": "@sociallane/widget-hero-saas-centered"
149
+ },
150
+ {
151
+ "slug": "hero-saas-split",
152
+ "package": "@sociallane/widget-hero-saas-split"
153
+ },
154
+ {
155
+ "slug": "hero-saas-stacked",
156
+ "package": "@sociallane/widget-hero-saas-stacked"
157
+ },
158
+ {
159
+ "slug": "hero-split",
160
+ "package": "@sociallane/widget-hero-split"
161
+ },
162
+ {
163
+ "slug": "hero-stacked-image",
164
+ "package": "@sociallane/widget-hero-stacked-image"
165
+ },
166
+ {
167
+ "slug": "intro-pattern",
168
+ "package": "@sociallane/widget-intro-pattern"
169
+ },
170
+ {
171
+ "slug": "intro-text",
172
+ "package": "@sociallane/widget-intro-text"
173
+ },
174
+ {
175
+ "slug": "logo-grid-centered",
176
+ "package": "@sociallane/widget-logo-grid-centered"
177
+ },
178
+ {
179
+ "slug": "logo-grid-row",
180
+ "package": "@sociallane/widget-logo-grid-row"
181
+ },
182
+ {
183
+ "slug": "logo-grid-split",
184
+ "package": "@sociallane/widget-logo-grid-split"
185
+ },
186
+ {
187
+ "slug": "nav-centered",
188
+ "package": "@sociallane/widget-nav-centered"
189
+ },
190
+ {
191
+ "slug": "nav-compact",
192
+ "package": "@sociallane/widget-nav-compact"
193
+ },
194
+ {
195
+ "slug": "nav-default",
196
+ "package": "@sociallane/widget-nav-default"
197
+ },
198
+ {
199
+ "slug": "nav-floating",
200
+ "package": "@sociallane/widget-nav-floating"
201
+ },
202
+ {
203
+ "slug": "nav-minimal",
204
+ "package": "@sociallane/widget-nav-minimal"
205
+ },
206
+ {
207
+ "slug": "newsletter",
208
+ "package": "@sociallane/widget-newsletter"
209
+ },
210
+ {
211
+ "slug": "newsletter-card",
212
+ "package": "@sociallane/widget-newsletter-card"
213
+ },
214
+ {
215
+ "slug": "newsletter-section",
216
+ "package": "@sociallane/widget-newsletter-section"
217
+ },
218
+ {
219
+ "slug": "outreach-dashboard",
220
+ "package": "@sociallane/widget-outreach-dashboard"
221
+ },
222
+ {
223
+ "slug": "page-hero-center",
224
+ "package": "@sociallane/widget-page-hero-center"
225
+ },
226
+ {
227
+ "slug": "page-hero-left",
228
+ "package": "@sociallane/widget-page-hero-left"
229
+ },
230
+ {
231
+ "slug": "pipeline-dashboard",
232
+ "package": "@sociallane/widget-pipeline-dashboard"
233
+ },
234
+ {
235
+ "slug": "posts-grid",
236
+ "package": "@sociallane/widget-posts-grid"
237
+ },
238
+ {
239
+ "slug": "posts-grid-overlay",
240
+ "package": "@sociallane/widget-posts-grid-overlay"
241
+ },
242
+ {
243
+ "slug": "pricing-table",
244
+ "package": "@sociallane/widget-pricing-table"
245
+ },
246
+ {
247
+ "slug": "sales-dashboard",
248
+ "package": "@sociallane/widget-sales-dashboard"
249
+ },
250
+ {
251
+ "slug": "section-stats",
252
+ "package": "@sociallane/widget-section-stats"
253
+ },
254
+ {
255
+ "slug": "services",
256
+ "package": "@sociallane/widget-services"
257
+ },
258
+ {
259
+ "slug": "simple-page-hero",
260
+ "package": "@sociallane/widget-simple-page-hero"
261
+ },
262
+ {
263
+ "slug": "social-proof",
264
+ "package": "@sociallane/widget-social-proof"
265
+ },
266
+ {
267
+ "slug": "social-proof-trust",
268
+ "package": "@sociallane/widget-social-proof-trust"
269
+ },
270
+ {
271
+ "slug": "testimonial-quote",
272
+ "package": "@sociallane/widget-testimonial-quote"
273
+ },
274
+ {
275
+ "slug": "testimonials-bento",
276
+ "package": "@sociallane/widget-testimonials-bento"
277
+ },
278
+ {
279
+ "slug": "testimonials-grid",
280
+ "package": "@sociallane/widget-testimonials-grid"
281
+ },
282
+ {
283
+ "slug": "testimonials-masonry",
284
+ "package": "@sociallane/widget-testimonials-masonry"
285
+ },
286
+ {
287
+ "slug": "widget-filter",
288
+ "package": "@sociallane/widget-widget-filter"
289
+ }
290
+ ]
291
+ }
@@ -484,8 +484,8 @@ function prepare_widget_filter_view( array $settings, string $widget_id ): array
484
484
  // Grid columns class
485
485
  $grid_columns = [
486
486
  '2' => 'grid-cols-1 sm:grid-cols-2',
487
- '3' => 'grid-cols-1 sm:grid-cols-2 lg:grid-cols-3',
488
- '4' => 'grid-cols-1 sm:grid-cols-2 lg:grid-cols-4',
487
+ '3' => 'grid-cols-1 sm:grid-cols-2 md:grid-cols-3',
488
+ '4' => 'grid-cols-1 sm:grid-cols-2 md:grid-cols-3 xl:grid-cols-4',
489
489
  ];
490
490
  $grid_class = $grid_columns[ $columns ] ?? $grid_columns['3'];
491
491
 
@@ -5,27 +5,15 @@
5
5
  * Run from plugin root: npm run build:widget-packages
6
6
  */
7
7
 
8
- import { cpSync, existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from 'fs';
8
+ import { cpSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
9
9
  import path from 'path';
10
10
  import { fileURLToPath } from 'url';
11
+ import { getWidgetSourceDir, syncWidgetManifest } from './lib/widgets-manifest.js';
11
12
 
12
13
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
13
14
  const pluginRoot = path.resolve(__dirname, '..');
14
- const widgetsDir = path.join(pluginRoot, 'packages', 'widgets');
15
15
  const npmWidgetsDir = path.join(pluginRoot, 'packages', 'npm-widgets');
16
-
17
- function getWidgetSlugs() {
18
- if (!existsSync(widgetsDir)) return [];
19
- const entries = readdirSync(widgetsDir, { withFileTypes: true });
20
- const slugs = [];
21
- for (const ent of entries) {
22
- if (!ent.isDirectory()) continue;
23
- const slug = ent.name;
24
- const phpFile = path.join(widgetsDir, slug, `${slug}.php`);
25
- if (existsSync(phpFile)) slugs.push(slug);
26
- }
27
- return slugs.sort((a, b) => a.localeCompare(b));
28
- }
16
+ const widgetsDir = getWidgetSourceDir(pluginRoot);
29
17
 
30
18
  function getRootVersion() {
31
19
  const pkgPath = path.join(pluginRoot, 'package.json');
@@ -79,7 +67,8 @@ This installs the SocialLane Elements plugin if needed, then adds this widget an
79
67
  }
80
68
 
81
69
  function main() {
82
- const slugs = getWidgetSlugs();
70
+ const manifest = syncWidgetManifest(pluginRoot);
71
+ const slugs = manifest.widgets.map((widget) => widget.slug);
83
72
  const version = getRootVersion();
84
73
  if (!existsSync(npmWidgetsDir)) mkdirSync(npmWidgetsDir, { recursive: true });
85
74
  for (const slug of slugs) {
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Generate packages/widget-manifest.json from widget sources on disk.
4
+ * Run from plugin root: npm run manifest:widgets
5
+ */
6
+
7
+ import path from 'path';
8
+ import { fileURLToPath } from 'url';
9
+ import { syncWidgetManifest, getWidgetManifestPath } from './lib/widgets-manifest.js';
10
+
11
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
12
+ const pluginRoot = path.resolve(__dirname, '..');
13
+
14
+ const manifest = syncWidgetManifest(pluginRoot);
15
+ const manifestPath = getWidgetManifestPath(pluginRoot);
16
+
17
+ console.log(
18
+ `Widget manifest updated: ${manifest.widgets.length} widgets (${manifest.source}) -> ${manifestPath}`
19
+ );