strata-css 1.2.6 → 1.2.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,62 +1,158 @@
1
- # Changelog
2
-
3
- All notable changes to Strata CSS will be documented here.
4
-
5
- ## [1.0.0] — 2026-05-10
6
-
7
- ### Components
8
- - `btn-primary`, `btn-secondary`, `btn-success`, `btn-danger`, `btn-warning`, `btn-info`, `btn-light`, `btn-dark` full semantic button set with hover, focus, and active states baked in
9
- - `card`, `card-header`, `card-body`, `card-footer` — composable card component
10
- - `container`, `row`, `col-*` — Bootstrap-compatible responsive grid across all six breakpoints
11
- - `modal` — dialog component with `data-st-toggle`, `data-st-dismiss`, and `data-st-backdrop` attribute API
12
- - `navbar`, `navbar-brand`, `navbar-nav` — navigation bar component
13
- - Skeleton loader — animated loading placeholder with `Strata.skeleton` JavaScript API
14
-
15
- ### Utilities
16
- - Spacing: `mt-*`, `mb-*`, `ms-*`, `me-*`, `pt-*`, `pb-*`, `px-*`, `py-*`, `mx-auto`, `my-*`
17
- - Display: `d-flex`, `d-none`, `d-block`, `d-grid`, `d-inline`, `d-inline-flex`, `d-inline-block`
18
- - Colors: `text-*`, `bg-*` all semantic colors (primary, secondary, success, danger, warning, info, light, dark, muted)
19
- - Sizing: `w-25`, `w-50`, `w-75`, `w-100`, `h-25`, `h-50`, `h-75`, `h-100`, `mw-100`, `mh-100`
20
- - Flexbox: `justify-content-*`, `align-items-*`, `align-self-*`, `flex-wrap`, `flex-nowrap`, `flex-grow-*`, `flex-shrink-*`
21
- - Position: `position-static`, `position-relative`, `position-absolute`, `position-fixed`, `position-sticky`
22
- - Overflow: `overflow-auto`, `overflow-hidden`, `overflow-scroll`, `overflow-visible`
23
- - Opacity: `opacity-0`, `opacity-25`, `opacity-50`, `opacity-75`, `opacity-100`
24
- - Visibility: `visible`, `invisible`
25
- - Z-index: `z-0` through `z-3`
26
- - Cursor: `cursor-pointer`, `cursor-default`, `cursor-not-allowed`, `cursor-wait`
27
- - Shadows: `shadow-none`, `shadow-sm`, `shadow`, `shadow-lg`
28
- - Transitions: `transition`, `transition-fast`, `transition-slow`, `transition-none`
29
- - Easing: `ease-in`, `ease-out`, `ease-in-out`, `ease-linear`
30
- - Arbitrary values: `mt-[24px]`, `bg-[#ff0000]`, `w-[347px]`, `transition-[background-color_0.3s_ease]`
31
- - Important variants: `!mt-0`, `!d-none`, `!p-0`
32
- - Breakpoint variants on all utilities: `col-md-6`, `d-lg-none`, `mt-xl-4`, `px-xxl-5`
33
-
34
- ### Theming
35
- - Three built-in themes: `light` (default), `dark`, `dim` applied via `data-st-theme` on `<html>`
36
- - Automatic system preference detection via `prefers-color-scheme` — no configuration needed
37
- - Unlimited custom themes via CSS custom properties: `[data-st-theme="brand"] { --st-primary: #7c3aed }`
38
- - All `--st-*` custom properties fully overridable in `:root` or any selector
39
- - Smooth theme transitions — all elements animate when the theme attribute changes
40
-
41
- ### State Management
42
- - `data-st-visible="true|false"` — fade + translateY transition for show/hide
43
- - `data-st-collapsed="true|false"`smooth `max-height` expand/collapse
44
- - `data-st-loading="true|false"` opacity reduction + pointer-events disabled
45
- - `data-st-disabled="true|false"` — opacity reduction + `cursor: not-allowed`
46
- - `data-st-theme="light|dark|dim|custom"` — live theme switching
47
-
48
- ### Build System
49
- - PostCSS plugin with O(1) class registry 1065 pre-computed entries, zero linear scanning
50
- - Multi-layer caching: dirty flag, file mtime, glob hash, config hash, output string cache
51
- - CSS `@layer` hierarchy: `st-base` → `st-components` → `st-utilities` — breakpoint order guaranteed, HTML class order irrelevant
52
- - Bootstrap-style breakpoints: xs (0px), sm (576px), md (768px), lg (992px), xl (1200px), xxl (1400px)
53
- - Custom breakpoints via `strata.config.js` `theme.breakpoints`
54
- - `prefers-reduced-motion` respected automatically — no configuration needed
55
- - CLI: `strata init` (scaffold), `strata --watch` (development), `strata --build` (production), `strata --minify` (minified production)
56
-
57
- ### Performance (vs Tailwind CSS 3 in watch mode)
58
- - Cold build: 1.89ms avg vs 7.21ms 3.8× faster
59
- - Warm rebuild: 0.14ms avg vs 2.70ms 19× faster
60
- - Warm p95: 0.23ms vs 6.12ms 26× faster
61
-
62
- Reproduce via `npm run benchmark`.
1
+ # Changelog
2
+
3
+ All notable changes to Strata CSS will be documented here.
4
+
5
+ ## [1.2.7] — 2026-06-15
6
+
7
+ ### Fixed
8
+ - **Components bundle (`dist/strata.components.js`) now creates the `Strata` namespace.** Each component's UMD wrapper attaches to `Strata.*` only `if (root.Strata)` exists, but the bundle never initialised it — so every component fell back to its own global (`StrataChart`, `StrataModal`, …) and `window.Strata` was never defined, breaking all `Strata.Chart.create(...)` / `Strata.Modal.open(...)` usage (e.g. blank charts in `examples/chart.html`). The bundle banner (`bin/strata.js`) now initialises `Strata` before the wrappers run.
9
+
10
+ ---
11
+
12
+ ## [1.2.6] 2026-06-05
13
+
14
+ ### Docs
15
+ - Versioning rules clarified and expanded in `CONTRIBUTING.md`
16
+ - All package `CLAUDE.md` files updated with complete API references
17
+ - `README.md` files added to `@strata-packages/picker` and `@strata-packages/forms`
18
+ - `CHANGELOG.md` files added to `@strata-packages/picker` and `@strata-packages/forms`
19
+ - Root `README.md` updated: version badge, forms/picker added to standalone packages table
20
+
21
+ ---
22
+
23
+ ## [1.2.5] 2026-06-04
24
+
25
+ ### Added `@strata-packages/picker`
26
+ - `theme` option — per-instance inline CSS variable overrides (primary, bg, text, radius, shadow, cellSize, fontSize)
27
+ - `className` option — extra class on popup for targeted CSS overrides
28
+
29
+ ---
30
+
31
+ ## [1.2.4] 2026-06-03
32
+
33
+ ### Added
34
+ - `@strata-packages/picker` — new standalone package: date, time, and datetime picker
35
+ - Zero dependencies, works standalone or as `Strata.Picker` with Strata CSS
36
+ - Declarative init via `data-st-datepicker`, `data-st-timepicker`, `data-st-datetimepicker`
37
+ - Date range selection with two-input mode and range highlight
38
+ - Preset shortcuts (built-in and custom)
39
+ - Month/year grid navigation
40
+ - `--stp-*` CSS variable system; auto-inherits `--st-*` tokens when Strata CSS is present
41
+
42
+ ### Fixed
43
+ - Picker popup now appends to `<body>` with no CSS opacity transition appears immediately on open
44
+ - `position: fixed` popup no longer adds scroll offset to viewport coordinates
45
+ - Picker rewritten as unified `createPicker` — date / time / datetime all working correctly
46
+
47
+ ---
48
+
49
+ ## [1.2.3]2026-06-02
50
+
51
+ ### Fixed
52
+ - `@strata-packages/forms` auto-init now recognises all `data-st-*` select attributes at DOMContentLoaded
53
+
54
+ ---
55
+
56
+ ## [1.2.2] — 2026-06-01
57
+
58
+ ### Added`@strata-packages/forms`
59
+ - Checkbox select mode: dropdown stays open while ticking, Select All row, group-level checkboxes, `checkboxDisplay`: `chips` / `count` / `list`
60
+ - `maxDisplay` fixed-height chip trigger with `+N` overflow badge
61
+ - Search input always rendered inside the dropdown (not above it)
62
+
63
+ ---
64
+
65
+ ## [1.2.1] — 2026-05-30
66
+
67
+ ### Fixed
68
+ - `@strata-packages/forms` backend-friendly `required` validation — triggers visible error state on custom trigger
69
+
70
+ ---
71
+
72
+ ## [1.2.0] — 2026-05-28
73
+
74
+ ### Added — `@strata-packages/forms`
75
+ - New standalone package: fully accessible custom select replacement
76
+ - Multi-select with chips, `maxItems`, searchable, clearable, grouped `<optgroup>`, creatable, avatar/custom render, async `loadOptions`, auto-width with viewport edge detection
77
+ - Native `<select>` stays in DOM — form submission works with any backend
78
+ - Declarative init via `data-st-select` and `data-st-*` option attributes
79
+
80
+ ---
81
+
82
+ ## [1.1.0] — 2026-05-20
83
+
84
+ ### Added
85
+ - Transition CSS variables: `--st-duration-theme`, `--st-easing-theme` — all hardcoded transition values replaced
86
+ - Sizing utilities: `max-w-{xs/sm/md/lg/xl/xxl/full/none}`, `min-w-{0/full/screen}`, `max-h-{full/screen/none}`, `min-h-{0/full/screen}`
87
+ - Arbitrary sizing: `max-w-[440px]`, `min-h-[300px]`, `max-h-[500px]`, `min-w-[200px]`
88
+ - Responsive variants added to 15 utility groups: `flex-{bp}`, `fw-{bp}`, `fst-{bp}`, `text-{bp}-{transform}`, `rounded-{bp}`, `shadow-{bp}`, `w-{bp}`, `h-{bp}`, `opacity-{bp}`, `overflow-{bp}`, `position-{bp}`, `cursor-{bp}`, `lh-{bp}`, `visible-{bp}`, `invisible-{bp}`
89
+ - Component CSS variable tokens: all hardcoded color values replaced with local CSS variables on `.badge`, `.btn-*`, `.btn-outline-*`, `.nav-pills .active`, `.list-group-item.active`, `.page-item.active`, `.dropdown-item.active`, `.progress-bar`, `.tooltip-inner`, `.navbar-dark`, `.card-img-overlay`, `.carousel-*`, `.table-dark`
90
+ - List utilities: `list-unstyled`, `list-inline`, `list-inline-item`, `list-disc`, `list-decimal`, `list-circle`, `list-square`, `list-none`, `list-lower-alpha`, `list-upper-alpha`, `list-lower-roman`, `list-upper-roman`, `list-inside`, `list-outside`, `list-spaced`
91
+ - Outline utilities: `outline-none`, `outline-{color}`, `outline-{1-5}`
92
+ - Label component: `.label` and `.label-{color}` aliases to `.badge` / `.badge-{color}` for Bootstrap 3 compatibility
93
+
94
+ ### Fixed
95
+ - `text-[15px]` → `font-size: 15px` (length unit correctly detected)
96
+ - `text-[#f00]` → `color: #f00` (color value correctly detected)
97
+ - `#`, `(`, `)`, `,` in arbitrary values now correctly escaped in CSS class selectors
98
+
99
+ ---
100
+
101
+ ## [1.0.0] — 2026-05-10
102
+
103
+ ### Components
104
+ - `btn-primary`, `btn-secondary`, `btn-success`, `btn-danger`, `btn-warning`, `btn-info`, `btn-light`, `btn-dark` — full semantic button set with hover, focus, and active states baked in
105
+ - `card`, `card-header`, `card-body`, `card-footer` — composable card component
106
+ - `container`, `row`, `col-*` — Bootstrap-compatible responsive grid across all six breakpoints
107
+ - `modal` — dialog component with `data-st-toggle`, `data-st-dismiss`, and `data-st-backdrop` attribute API
108
+ - `navbar`, `navbar-brand`, `navbar-nav` — navigation bar component
109
+ - Skeleton loader — animated loading placeholder with `Strata.skeleton` JavaScript API
110
+
111
+ ### Utilities
112
+ - Spacing: `mt-*`, `mb-*`, `ms-*`, `me-*`, `pt-*`, `pb-*`, `px-*`, `py-*`, `mx-auto`, `my-*`
113
+ - Display: `d-flex`, `d-none`, `d-block`, `d-grid`, `d-inline`, `d-inline-flex`, `d-inline-block`
114
+ - Colors: `text-*`, `bg-*` — all semantic colors (primary, secondary, success, danger, warning, info, light, dark, muted)
115
+ - Sizing: `w-25`, `w-50`, `w-75`, `w-100`, `h-25`, `h-50`, `h-75`, `h-100`, `mw-100`, `mh-100`
116
+ - Flexbox: `justify-content-*`, `align-items-*`, `align-self-*`, `flex-wrap`, `flex-nowrap`, `flex-grow-*`, `flex-shrink-*`
117
+ - Position: `position-static`, `position-relative`, `position-absolute`, `position-fixed`, `position-sticky`
118
+ - Overflow: `overflow-auto`, `overflow-hidden`, `overflow-scroll`, `overflow-visible`
119
+ - Opacity: `opacity-0`, `opacity-25`, `opacity-50`, `opacity-75`, `opacity-100`
120
+ - Visibility: `visible`, `invisible`
121
+ - Z-index: `z-0` through `z-3`
122
+ - Cursor: `cursor-pointer`, `cursor-default`, `cursor-not-allowed`, `cursor-wait`
123
+ - Shadows: `shadow-none`, `shadow-sm`, `shadow`, `shadow-lg`
124
+ - Transitions: `transition`, `transition-fast`, `transition-slow`, `transition-none`
125
+ - Easing: `ease-in`, `ease-out`, `ease-in-out`, `ease-linear`
126
+ - Arbitrary values: `mt-[24px]`, `bg-[#ff0000]`, `w-[347px]`, `transition-[background-color_0.3s_ease]`
127
+ - Important variants: `!mt-0`, `!d-none`, `!p-0`
128
+ - Breakpoint variants on all utilities: `col-md-6`, `d-lg-none`, `mt-xl-4`, `px-xxl-5`
129
+
130
+ ### Theming
131
+ - Three built-in themes: `light` (default), `dark`, `dim` — applied via `data-st-theme` on `<html>`
132
+ - Automatic system preference detection via `prefers-color-scheme` — no configuration needed
133
+ - Unlimited custom themes via CSS custom properties: `[data-st-theme="brand"] { --st-primary: #7c3aed }`
134
+ - All `--st-*` custom properties fully overridable in `:root` or any selector
135
+ - Smooth theme transitions — all elements animate when the theme attribute changes
136
+
137
+ ### State Management
138
+ - `data-st-visible="true|false"` — fade + translateY transition for show/hide
139
+ - `data-st-collapsed="true|false"` — smooth `max-height` expand/collapse
140
+ - `data-st-loading="true|false"` — opacity reduction + pointer-events disabled
141
+ - `data-st-disabled="true|false"` — opacity reduction + `cursor: not-allowed`
142
+ - `data-st-theme="light|dark|dim|custom"` — live theme switching
143
+
144
+ ### Build System
145
+ - PostCSS plugin with O(1) class registry — 1065 pre-computed entries, zero linear scanning
146
+ - Multi-layer caching: dirty flag, file mtime, glob hash, config hash, output string cache
147
+ - CSS `@layer` hierarchy: `st-base` → `st-components` → `st-utilities` — breakpoint order guaranteed, HTML class order irrelevant
148
+ - Bootstrap-style breakpoints: xs (0px), sm (576px), md (768px), lg (992px), xl (1200px), xxl (1400px)
149
+ - Custom breakpoints via `strata.config.js` `theme.breakpoints`
150
+ - `prefers-reduced-motion` respected automatically — no configuration needed
151
+ - CLI: `strata init` (scaffold), `strata --watch` (development), `strata --build` (production), `strata --minify` (minified production)
152
+
153
+ ### Performance (vs Tailwind CSS 3 in watch mode)
154
+ - Cold build: 1.89ms avg vs 7.21ms — 3.8× faster
155
+ - Warm rebuild: 0.14ms avg vs 2.70ms — 19× faster
156
+ - Warm p95: 0.23ms vs 6.12ms — 26× faster
157
+
158
+ Reproduce via `npm run benchmark`.
package/README.md CHANGED
@@ -5,7 +5,7 @@
5
5
  **A modern CSS framework combining Bootstrap's component architecture with Tailwind's JIT processing.**
6
6
 
7
7
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
8
- [![Version](https://img.shields.io/badge/version-1.0.4-green.svg)]()
8
+ [![Version](https://img.shields.io/badge/version-1.2.6-green.svg)]()
9
9
  [![Node](https://img.shields.io/badge/node-%3E%3D18.0.0-brightgreen.svg)]()
10
10
  [![npm](https://img.shields.io/badge/npm-strata--css-red.svg)](https://www.npmjs.com/package/strata-css)
11
11
  [![css-framework](https://img.shields.io/badge/css--framework-%E2%9C%93-blue.svg)]()
@@ -383,9 +383,11 @@ All Strata plugins are available as independent packages. Use them without Strat
383
383
 
384
384
  | Package | Standalone global | With Strata | Install |
385
385
  |---|---|---|---|
386
- | `@strata-css/skeleton-loader` | `SkeletonLoader` | `Strata.skeleton` | `npm i @strata-css/skeleton-loader` |
387
- | `@strata-css/modal` | `StrataModal` | `Strata.Modal` | `npm i @strata-css/modal` |
388
- | `@strata-css/chart` | `StrataChart` | `Strata.Chart` | `npm i @strata-css/chart` |
386
+ | `@strata-packages/forms` | `StrataForms` | `Strata.Forms` | `npm i @strata-packages/forms` |
387
+ | `@strata-packages/picker` | `StrataPicker` | `Strata.Picker` | `npm i @strata-packages/picker` |
388
+ | `@strata-packages/skeleton-loader` | `SkeletonLoader` | `Strata.skeleton` | `npm i @strata-packages/skeleton-loader` |
389
+ | `@strata-packages/modal` | `StrataModal` | `Strata.Modal` | `npm i @strata-packages/modal` |
390
+ | `@strata-packages/chart` | `StrataChart` | `Strata.Chart` | `npm i @strata-packages/chart` |
389
391
 
390
392
  ### How detection works
391
393
 
@@ -395,18 +397,18 @@ When `strata.components.js` is loaded it sets `data-strata` on `<html>`. Each pl
395
397
 
396
398
  ```html
397
399
  <!-- Skeleton -->
398
- <link rel="stylesheet" href="node_modules/@strata-css/skeleton-loader/skeleton-loader.css">
399
- <script src="node_modules/@strata-css/skeleton-loader/skeleton-loader.js"></script>
400
+ <link rel="stylesheet" href="node_modules/@strata-packages/skeleton-loader/skeleton-loader.css">
401
+ <script src="node_modules/@strata-packages/skeleton-loader/skeleton-loader.js"></script>
400
402
  <script>SkeletonLoader.init('.card')</script>
401
403
 
402
404
  <!-- Modal -->
403
- <link rel="stylesheet" href="node_modules/@strata-css/modal/modal.css">
404
- <script src="node_modules/@strata-css/modal/modal.js"></script>
405
+ <link rel="stylesheet" href="node_modules/@strata-packages/modal/modal.css">
406
+ <script src="node_modules/@strata-packages/modal/modal.js"></script>
405
407
  <script>StrataModal.open('#myModal')</script>
406
408
 
407
409
  <!-- Chart (requires Three.js) -->
408
410
  <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
409
- <script src="node_modules/@strata-css/chart/chart.js"></script>
411
+ <script src="node_modules/@strata-packages/chart/chart.js"></script>
410
412
  <script>StrataChart.create('#myChart', { type: 'bar', data: [...] })</script>
411
413
  ```
412
414
 
package/bin/strata.js CHANGED
@@ -90,7 +90,11 @@ async function build(cssMinify = false, jsMinify = true) {
90
90
  const jsDest = path.join(path.dirname(outputFile), 'strata.components.js')
91
91
  if (fs.existsSync(componentsDir)) {
92
92
  const files = fs.readdirSync(componentsDir).filter(f => f.endsWith('.js')).sort()
93
+ // Create the shared Strata namespace BEFORE the package UMD wrappers run, so
94
+ // each one attaches to Strata.* (their `if (root.Strata)` branch) instead of
95
+ // falling back to a separate StrataModal/StrataChart/etc. global.
93
96
  const banner = `/*! Strata Components — built ${new Date().toISOString().slice(0,10)} */\n`
97
+ + `;(function(g){g.Strata=g.Strata||{}})(typeof globalThis!=='undefined'?globalThis:this);\n`
94
98
  const parts = files.map(f => fs.readFileSync(path.join(componentsDir, f), 'utf8'))
95
99
  packageFiles.forEach(p => { if (fs.existsSync(p)) parts.push(fs.readFileSync(p, 'utf8')) })
96
100
  const raw = parts.join('\n')
@@ -178,9 +182,9 @@ function detectFramework(cwd) {
178
182
  // ─── Init helpers ─────────────────────────────────────────────────────
179
183
 
180
184
  const PACKAGES = [
181
- { name: '@strata-css/modal', label: 'modal — attribute-driven modal dialogs' },
182
- { name: '@strata-css/skeleton-loader',label: 'skeleton-loader — shimmer loading placeholders' },
183
- { name: '@strata-css/chart', label: 'chart — Three.js data visualisations' },
185
+ { name: '@strata-packages/modal', label: 'modal — attribute-driven modal dialogs' },
186
+ { name: '@strata-packages/skeleton-loader',label: 'skeleton-loader — shimmer loading placeholders' },
187
+ { name: '@strata-packages/chart', label: 'chart — Three.js data visualisations' },
184
188
  ]
185
189
 
186
190
  const FRAMEWORK_DEV = {
@@ -254,10 +258,10 @@ async function askCheckbox(rl, items) {
254
258
  }
255
259
 
256
260
  function packageUsageSnippet(pkgName) {
257
- if (pkgName === '@strata-css/modal') return `
261
+ if (pkgName === '@strata-packages/modal') return `
258
262
  <!-- Modal usage (standalone) -->
259
- <link rel="stylesheet" href="node_modules/@strata-css/modal/modal.css">
260
- <script src="node_modules/@strata-css/modal/modal.js"></script>
263
+ <link rel="stylesheet" href="node_modules/@strata-packages/modal/modal.css">
264
+ <script src="node_modules/@strata-packages/modal/modal.js"></script>
261
265
 
262
266
  <button data-st-toggle="modal" data-st-target="#myModal">Open</button>
263
267
  <div class="modal" id="myModal" aria-hidden="true">
@@ -270,10 +274,10 @@ function packageUsageSnippet(pkgName) {
270
274
  </div></div>
271
275
  </div>`
272
276
 
273
- if (pkgName === '@strata-css/skeleton-loader') return `
277
+ if (pkgName === '@strata-packages/skeleton-loader') return `
274
278
  <!-- Skeleton loader usage (standalone) -->
275
- <link rel="stylesheet" href="node_modules/@strata-css/skeleton-loader/skeleton-loader.css">
276
- <script src="node_modules/@strata-css/skeleton-loader/skeleton-loader.js"></script>
279
+ <link rel="stylesheet" href="node_modules/@strata-packages/skeleton-loader/skeleton-loader.css">
280
+ <script src="node_modules/@strata-packages/skeleton-loader/skeleton-loader.js"></script>
277
281
 
278
282
  <div class="card" data-st-skeleton="true">
279
283
  <div class="card-body"><p>Content loading...</p></div>
@@ -283,10 +287,10 @@ function packageUsageSnippet(pkgName) {
283
287
  fetchData().then(() => SkeletonLoader.reveal())
284
288
  </script>`
285
289
 
286
- if (pkgName === '@strata-css/chart') return `
290
+ if (pkgName === '@strata-packages/chart') return `
287
291
  <!-- Chart usage (standalone, requires Three.js) -->
288
292
  <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
289
- <script src="node_modules/@strata-css/chart/chart.js"></script>
293
+ <script src="node_modules/@strata-packages/chart/chart.js"></script>
290
294
 
291
295
  <canvas id="myChart"></canvas>
292
296
  <script>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "strata-css",
3
- "version": "1.2.6",
3
+ "version": "1.2.7",
4
4
  "_versioningNote": "Stable: 1.0.0 / 1.1.0 / 2.0.0 | Beta: 1.1.0-beta.1 / 1.1.0-beta.2",
5
5
  "description": "A modern CSS framework combining Bootstrap components with Tailwind JIT processing",
6
6
  "main": "src/index.js",
@@ -99,6 +99,10 @@ interface ChartOptions {
99
99
  onReady?: (chart: StrataChart) => void
100
100
  onChange?: (view: ChartView) => void
101
101
  onClick?: (point: { label: string; value: number; category: string; index: number }) => void
102
+
103
+ // Three.js is lazy-loaded from this URL if window.THREE is absent. Set to ''
104
+ // to require the host to pre-load it.
105
+ threeUrl?: string
102
106
  }
103
107
 
104
108
  interface OrbitControlsInstance {
@@ -115,7 +119,10 @@ interface OrbitControlsInstance {
115
119
  interface StrataNamespace { Chart: ChartPlugin }
116
120
 
117
121
  interface ChartPlugin {
118
- create(selector: string | Element, options: ChartOptions): StrataChart | null
122
+ // Synchronous when window.THREE is present; otherwise lazy-loads Three.js and
123
+ // resolves to the instance (or null on failure).
124
+ create(selector: string | Element, options: ChartOptions): StrataChart | null | Promise<StrataChart | null>
125
+ load(url?: string): Promise<unknown>
119
126
  destroyAll(): void
120
127
  }
121
128
 
@@ -157,6 +164,8 @@ const CAMERA_2D = { x: 0, y: 2, z: 22, fov: 18 }
157
164
  const DEFAULT_COLORS = ['#4a90e2', '#e25f4a', '#50c878', '#f5a623', '#9b59b6', '#1abc9c']
158
165
  const VALID_TYPES = ['bar', 'line', 'pie', 'scatter'] as ChartType[]
159
166
  const MAX_POINTS = 100_000
167
+ // Three.js is lazy-loaded on first chart creation if window.THREE is absent.
168
+ const DEFAULT_THREE_URL = 'https://cdn.jsdelivr.net/npm/three@0.160.0/build/three.min.js'
160
169
  const STRIP_HTML = /<[^>]*>/g
161
170
  const SCALE_STEPS = 5
162
171
  const GRID_COLOR_NORMAL = 0xd4d4d4
@@ -1097,29 +1106,54 @@ class StrataChart {
1097
1106
 
1098
1107
  // ─── Bootstrap IIFE ───────────────────────────────────────────────────────────
1099
1108
 
1100
- ;(function (win: Window & typeof globalThis & { Strata?: Partial<StrataNamespace>; StrataChart?: Partial<StrataNamespace['Chart']> }) {
1101
- if (!(win as unknown as Record<string, unknown>)['THREE']) {
1102
- console.error('[Strata Chart] Three.js (window.THREE) is required. Load it before this script.')
1103
- return
1109
+ ;(function (win: Window & typeof globalThis & { THREE?: unknown; Strata?: Partial<StrataNamespace>; StrataChart?: Partial<StrataNamespace['Chart']> }) {
1110
+ // Lazy Three.js loader fetched only on first chart creation if absent.
1111
+ let threeCache: Promise<unknown> | null = null
1112
+ function loadThree(url?: string): Promise<unknown> {
1113
+ if (win.THREE) return Promise.resolve(win.THREE)
1114
+ if (!url) return Promise.reject(new Error('[Strata Chart] Three.js not found and no threeUrl configured.'))
1115
+ if (threeCache) return threeCache
1116
+ threeCache = new Promise((resolve, reject) => {
1117
+ const s = document.createElement('script')
1118
+ s.src = url; s.async = true
1119
+ s.onload = () => { if (win.THREE) resolve(win.THREE); else { threeCache = null; reject(new Error('[Strata Chart] Three.js did not register after loading ' + url)) } }
1120
+ s.onerror = () => { threeCache = null; reject(new Error('[Strata Chart] Failed to load ' + url)) }
1121
+ document.head.appendChild(s)
1122
+ })
1123
+ return threeCache
1104
1124
  }
1105
1125
 
1106
- const api = {
1107
- create(selector: string | Element, options: ChartOptions): StrataChart | null {
1108
- const container = typeof selector === 'string' ? document.querySelector(selector) : selector as Element
1109
- if (!container) { console.error(`[Strata Chart] Element not found: ${String(selector)}`); return null }
1110
- if (registry.has(container)) {
1111
- console.warn('[Strata Chart] Chart already mounted here. Call .destroy() first.')
1112
- return registry.get(container)!
1113
- }
1114
- if (!Array.isArray(options?.data)) { console.error('[Strata Chart] options.data must be an array.'); return null }
1115
- if (options.type && !VALID_TYPES.includes(options.type)) {
1116
- console.error(`[Strata Chart] Invalid type "${options.type}". Use: ${VALID_TYPES.join(', ')}`)
1117
- return null
1118
- }
1119
- const instance = new StrataChart(container as HTMLElement, options)
1120
- registry.set(container, instance)
1121
- return instance
1126
+ // Validate + construct. Assumes Three.js is present.
1127
+ function build(selector: string | Element, options: ChartOptions): StrataChart | null {
1128
+ const container = typeof selector === 'string' ? document.querySelector(selector) : selector as Element
1129
+ if (!container) { console.error(`[Strata Chart] Element not found: ${String(selector)}`); return null }
1130
+ if (registry.has(container)) {
1131
+ console.warn('[Strata Chart] Chart already mounted here. Call .destroy() first.')
1132
+ return registry.get(container)!
1133
+ }
1134
+ if (!Array.isArray(options?.data)) { console.error('[Strata Chart] options.data must be an array.'); return null }
1135
+ if (options.type && !VALID_TYPES.includes(options.type)) {
1136
+ console.error(`[Strata Chart] Invalid type "${options.type}". Use: ${VALID_TYPES.join(', ')}`)
1137
+ return null
1138
+ }
1139
+ const instance = new StrataChart(container as HTMLElement, options)
1140
+ registry.set(container, instance)
1141
+ return instance
1142
+ }
1143
+
1144
+ const api: ChartPlugin = {
1145
+ // Synchronous + unchanged when Three.js is already present. If absent, it is
1146
+ // lazy-loaded and create() returns a Promise<instance> (override the source
1147
+ // with options.threeUrl, or '' to require pre-load).
1148
+ create(selector: string | Element, options: ChartOptions): StrataChart | null | Promise<StrataChart | null> {
1149
+ options = options || ({} as ChartOptions)
1150
+ if (win.THREE) return build(selector, options)
1151
+ const url = options.threeUrl === undefined ? DEFAULT_THREE_URL : options.threeUrl
1152
+ return loadThree(url)
1153
+ .then(() => build(selector, options))
1154
+ .catch((err: Error) => { console.error(err.message || err); return null })
1122
1155
  },
1156
+ load(url?: string): Promise<unknown> { return loadThree(url === undefined ? DEFAULT_THREE_URL : url) },
1123
1157
  destroyAll() { registry.forEach(inst => inst.destroy()) },
1124
1158
  }
1125
1159