@wpmoo/ui 1.0.0-rc.8 → 1.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.
- package/ASSET_LICENSE.md +1 -1
- package/LICENSE +28 -0
- package/README.md +34 -6
- package/certification.json +3 -2
- package/dist/assets/css/moo-ui.css +634 -33
- package/dist/assets/css/moo-ui.min.css +10 -31
- package/dist/assets/css/moo.css +624 -30
- package/dist/assets/css/moo.min.css +10 -32
- package/dist/js/chart.js +23 -21
- package/dist/js/chart.min.js +5 -5
- package/dist/js/combobox.js +18 -65
- package/dist/js/context-menu.js +16 -68
- package/dist/js/datatable.js +39 -22
- package/dist/js/datepicker.js +4 -3
- package/dist/js/datepicker.min.js +4 -3
- package/dist/js/moo-ui.js +160 -15402
- package/dist/js/moo-ui.min.js +3 -23
- package/dist/js/sheet.js +46 -0
- package/dist/js/sidebar.js +5 -4
- package/dist/js/slider.js +12 -47
- package/dist/js/state.js +76 -0
- package/dist/release-manifest.json +6 -6
- package/package.json +5 -3
- package/scss/_components.scss +2 -2
- package/scss/_config.scss +15 -21
- package/scss/_settings.scss +0 -3
- package/scss/components/_accordion.scss +1 -12
- package/scss/components/_alert.scss +1 -12
- package/scss/components/_avatar.scss +1 -16
- package/scss/components/_badge.scss +1 -0
- package/scss/components/_breadcrumb.scss +1 -12
- package/scss/components/_button.scss +1 -29
- package/scss/components/_button_group.scss +1 -25
- package/scss/components/_card.scss +1 -29
- package/scss/components/_checkbox.scss +1 -38
- package/scss/components/_close_button.scss +1 -9
- package/scss/components/_collapsible.scss +1 -0
- package/scss/components/_combobox.scss +1 -6
- package/scss/components/_context-menu.scss +1 -11
- package/scss/components/_datatable.scss +46 -85
- package/scss/components/_datepicker.scss +1 -0
- package/scss/components/_dialog.scss +1 -14
- package/scss/components/_dropdown.scss +5 -51
- package/scss/components/_field.scss +6 -37
- package/scss/components/_input.scss +1 -5
- package/scss/components/_input_group.scss +1 -51
- package/scss/components/_kbd.scss +1 -0
- package/scss/components/_menubar.scss +1 -0
- package/scss/components/_navigation.scss +76 -6
- package/scss/components/_pagination.scss +1 -13
- package/scss/components/_popover.scss +1 -22
- package/scss/components/_progress.scss +1 -3
- package/scss/components/_radio_group.scss +105 -6
- package/scss/components/_search_trigger.scss +1 -2
- package/scss/components/_select.scss +1 -0
- package/scss/components/_separator.scss +1 -6
- package/scss/components/_sheet.scss +1 -17
- package/scss/components/_sidebar.scss +1 -2
- package/scss/components/_skeleton.scss +1 -8
- package/scss/components/_slider.scss +1 -2
- package/scss/components/_spinner.scss +1 -7
- package/scss/components/_switch.scss +1 -4
- package/scss/components/_table.scss +1 -2
- package/scss/components/_tabs.scss +1 -24
- package/scss/components/_textarea.scss +1 -0
- package/scss/components/_toast.scss +1 -4
- package/scss/components/_toggle_group.scss +1 -3
- package/scss/components/_tooltip.scss +1 -20
- package/scss/components/sidebar/_base.scss +0 -7
- package/scss/components/sidebar/_collapsed.scss +0 -6
- package/scss/components/sidebar/_identity.scss +0 -1
- package/scss/components/sidebar/_menus.scss +0 -17
- package/scss/foundations/_backdrop.scss +0 -26
- package/scss/foundations/_focus.scss +0 -56
- package/scss/foundations/_scope.scss +19 -0
- package/scss/layouts/_app.scss +5 -7
- package/scss/layouts/_page_grid.scss +27 -0
- package/scss/layouts/app/sidebar/_base.scss +0 -33
- package/scss/layouts/app/sidebar/_default.scss +2 -8
- package/scss/layouts/app/sidebar/_floating.scss +1 -9
- package/scss/layouts/app/sidebar/_inset.scss +5 -2
- package/scss/mixins/_banner.scss +9 -3
- package/scss/moo-core.scss +3 -6
- package/scss/moo-ui.scss +9 -5
- package/scss/settings/_bootstrap_overrides.scss +0 -8
- package/scss/settings/_component_variables.scss +4 -266
- package/scss/settings/_forms.scss +1 -38
- package/scss/settings/_palette.scss +0 -42
- package/scss/themes/_root.scss +4 -0
- package/scss/themes/_standalone.scss +1 -3
- package/scss/themes/_theme.scss +4 -0
- package/scss/utilities/_background_color.scss +18 -0
- package/scss/utilities/_border.scss +4 -0
- package/dist/js/theme-prepaint.js +0 -91
package/dist/js/sheet.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Moo UI sheet.js v1.0.0 (https://wpmoo.org/)
|
|
3
|
+
* Copyright 2026 WPMoo Authors
|
|
4
|
+
* Licensed under MIT (https://github.com/wpmoo-org/ui/blob/main/LICENSE)
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// src/js/components/sheet.js
|
|
8
|
+
var states = /* @__PURE__ */ new WeakMap();
|
|
9
|
+
function initSheets(root = document) {
|
|
10
|
+
if (states.has(root)) {
|
|
11
|
+
return states.get(root);
|
|
12
|
+
}
|
|
13
|
+
const documentRoot = root.nodeType === 9 ? root : root.ownerDocument;
|
|
14
|
+
const Offcanvas = documentRoot?.defaultView?.bootstrap?.Offcanvas;
|
|
15
|
+
if (!Offcanvas) {
|
|
16
|
+
return () => {
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
const sheets = Array.from(root.querySelectorAll(".offcanvas.sheet"));
|
|
20
|
+
const focusInitialField = (event) => {
|
|
21
|
+
if (event.target === event.currentTarget) {
|
|
22
|
+
event.currentTarget.querySelector("[autofocus]:not(:disabled)")?.focus();
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
const dispose = () => {
|
|
26
|
+
if (states.get(root) !== dispose) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
sheets.forEach((sheet) => {
|
|
30
|
+
sheet.removeEventListener("shown.bs.offcanvas", focusInitialField);
|
|
31
|
+
});
|
|
32
|
+
states.delete(root);
|
|
33
|
+
};
|
|
34
|
+
states.set(root, dispose);
|
|
35
|
+
sheets.forEach((sheet) => {
|
|
36
|
+
sheet.addEventListener("shown.bs.offcanvas", focusInitialField);
|
|
37
|
+
if (sheet.dataset.sheetOpenOnLoad === "true") {
|
|
38
|
+
sheet.removeAttribute("data-sheet-open-on-load");
|
|
39
|
+
Offcanvas.getOrCreateInstance(sheet).show();
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
return dispose;
|
|
43
|
+
}
|
|
44
|
+
export {
|
|
45
|
+
initSheets
|
|
46
|
+
};
|
package/dist/js/sidebar.js
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* Moo UI sidebar.js v1.0.0
|
|
3
|
-
* Copyright 2026 WPMoo
|
|
2
|
+
* Moo UI sidebar.js v1.0.0 (https://wpmoo.org/)
|
|
3
|
+
* Copyright 2026 WPMoo Authors
|
|
4
4
|
* Licensed under MIT (https://github.com/wpmoo-org/ui/blob/main/LICENSE)
|
|
5
5
|
*/
|
|
6
|
+
|
|
6
7
|
var __defProp = Object.defineProperty;
|
|
7
8
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
8
9
|
|
|
9
10
|
// src/js/theme-owner.js
|
|
10
11
|
var OWNER_SELECTOR = '.moo-ui[data-bs-theme="light"], .moo-ui[data-bs-theme="dark"]';
|
|
11
|
-
var PORTAL_SELECTOR = "[data-moo-overlay-
|
|
12
|
+
var PORTAL_SELECTOR = "[data-moo-overlay-host]";
|
|
12
13
|
function documentFor(node) {
|
|
13
14
|
if (node?.nodeType === 9) return node;
|
|
14
15
|
if (node?.ownerDocument) return node.ownerDocument;
|
|
@@ -249,7 +250,7 @@ var _Sidebar = class _Sidebar {
|
|
|
249
250
|
_positionDropdown(control) {
|
|
250
251
|
const item = control?.closest?.(".sidebar-menu-item");
|
|
251
252
|
const isHeaderWorkspace = control?.classList.contains("sidebar-menu-button--workspace") && control.closest('[data-slot="sidebar-header"]');
|
|
252
|
-
const isFooterAccount = control?.
|
|
253
|
+
const isFooterAccount = control?.closest(".sidebar-menu-item--account") && control.closest('[data-slot="sidebar-footer"]');
|
|
253
254
|
if (!control || !item || !(isHeaderWorkspace || isFooterAccount) || !this._isDesktop()) {
|
|
254
255
|
this._clearDropdownPosition(control);
|
|
255
256
|
return;
|
package/dist/js/slider.js
CHANGED
|
@@ -1,23 +1,20 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* Moo UI slider.js v1.0.0
|
|
3
|
-
* Copyright 2026 WPMoo
|
|
2
|
+
* Moo UI slider.js v1.0.0 (https://wpmoo.org/)
|
|
3
|
+
* Copyright 2026 WPMoo Authors
|
|
4
4
|
* Licensed under MIT (https://github.com/wpmoo-org/ui/blob/main/LICENSE)
|
|
5
5
|
*/
|
|
6
|
-
const instances = new WeakMap();
|
|
7
6
|
|
|
7
|
+
const instances = /* @__PURE__ */ new WeakMap();
|
|
8
8
|
function asNumber(value, fallback) {
|
|
9
9
|
const number = Number(value);
|
|
10
10
|
return Number.isFinite(number) ? number : fallback;
|
|
11
11
|
}
|
|
12
|
-
|
|
13
12
|
function inputMinimum(input) {
|
|
14
13
|
return asNumber(input.min, 0);
|
|
15
14
|
}
|
|
16
|
-
|
|
17
15
|
function inputMaximum(input) {
|
|
18
16
|
return asNumber(input.max, 100);
|
|
19
17
|
}
|
|
20
|
-
|
|
21
18
|
function inputStep(input) {
|
|
22
19
|
if (!input.step || input.step === "any") {
|
|
23
20
|
return 1;
|
|
@@ -25,11 +22,9 @@ function inputStep(input) {
|
|
|
25
22
|
const step = Number(input.step);
|
|
26
23
|
return Number.isFinite(step) && step > 0 ? step : 1;
|
|
27
24
|
}
|
|
28
|
-
|
|
29
25
|
function clamp(value, min, max) {
|
|
30
26
|
return Math.min(Math.max(value, min), max);
|
|
31
27
|
}
|
|
32
|
-
|
|
33
28
|
function decimalPlaces(value) {
|
|
34
29
|
const text = String(value);
|
|
35
30
|
if (!text.includes(".")) {
|
|
@@ -37,7 +32,6 @@ function decimalPlaces(value) {
|
|
|
37
32
|
}
|
|
38
33
|
return text.split(".").at(-1).length;
|
|
39
34
|
}
|
|
40
|
-
|
|
41
35
|
function snapToStep(value, input) {
|
|
42
36
|
const min = inputMinimum(input);
|
|
43
37
|
const max = inputMaximum(input);
|
|
@@ -49,29 +43,24 @@ function snapToStep(value, input) {
|
|
|
49
43
|
const precision = Math.max(decimalPlaces(step), decimalPlaces(min));
|
|
50
44
|
return clamp(Number(snapped.toFixed(precision)), min, max);
|
|
51
45
|
}
|
|
52
|
-
|
|
53
46
|
function valuePercent(input) {
|
|
54
47
|
const min = inputMinimum(input);
|
|
55
48
|
const max = inputMaximum(input);
|
|
56
49
|
if (max <= min) {
|
|
57
50
|
return 0;
|
|
58
51
|
}
|
|
59
|
-
return (
|
|
52
|
+
return (asNumber(input.value, min) - min) / (max - min) * 100;
|
|
60
53
|
}
|
|
61
|
-
|
|
62
54
|
function displayValue(input) {
|
|
63
55
|
return input.value || String(inputMinimum(input));
|
|
64
56
|
}
|
|
65
|
-
|
|
66
|
-
export default class MooSlider {
|
|
57
|
+
class MooSlider {
|
|
67
58
|
static getInstance(element) {
|
|
68
59
|
return element?.nodeType === 1 ? instances.get(element) || null : null;
|
|
69
60
|
}
|
|
70
|
-
|
|
71
61
|
static getOrCreateInstance(element, config = {}) {
|
|
72
62
|
return MooSlider.getInstance(element) || new MooSlider(element, config);
|
|
73
63
|
}
|
|
74
|
-
|
|
75
64
|
constructor(element, config = {}) {
|
|
76
65
|
if (element?.nodeType !== 1 || !element.matches("[data-slider]")) {
|
|
77
66
|
throw new TypeError("MooSlider requires a [data-slider] root element.");
|
|
@@ -80,7 +69,6 @@ export default class MooSlider {
|
|
|
80
69
|
if (existing) {
|
|
81
70
|
return existing;
|
|
82
71
|
}
|
|
83
|
-
|
|
84
72
|
this._element = element;
|
|
85
73
|
this._document = element.ownerDocument;
|
|
86
74
|
this._window = this._document.defaultView;
|
|
@@ -94,19 +82,16 @@ export default class MooSlider {
|
|
|
94
82
|
);
|
|
95
83
|
this._track = element.querySelector("[data-slider-track]");
|
|
96
84
|
this._output = element.querySelector("[data-slider-output]");
|
|
97
|
-
|
|
98
85
|
if (this._inputs.length < 1 || this._inputs.length > 2) {
|
|
99
86
|
throw new TypeError("MooSlider requires one or two native range inputs.");
|
|
100
87
|
}
|
|
101
88
|
if (!this._track) {
|
|
102
89
|
throw new TypeError("MooSlider requires a [data-slider-track] element.");
|
|
103
90
|
}
|
|
104
|
-
|
|
105
91
|
instances.set(element, this);
|
|
106
92
|
this._bindEvents();
|
|
107
93
|
this._sync();
|
|
108
94
|
}
|
|
109
|
-
|
|
110
95
|
dispose() {
|
|
111
96
|
if (this._disposed) return;
|
|
112
97
|
this._disposed = true;
|
|
@@ -120,7 +105,6 @@ export default class MooSlider {
|
|
|
120
105
|
instances.delete(this._element);
|
|
121
106
|
}
|
|
122
107
|
}
|
|
123
|
-
|
|
124
108
|
_listen(target, type, handler, options) {
|
|
125
109
|
if (!target) {
|
|
126
110
|
return;
|
|
@@ -128,7 +112,6 @@ export default class MooSlider {
|
|
|
128
112
|
target.addEventListener(type, handler, options);
|
|
129
113
|
this._listeners.push({ target, type, handler, options });
|
|
130
114
|
}
|
|
131
|
-
|
|
132
115
|
_listenDuringDrag(target, type, handler, options) {
|
|
133
116
|
if (!target) {
|
|
134
117
|
return;
|
|
@@ -136,7 +119,6 @@ export default class MooSlider {
|
|
|
136
119
|
target.addEventListener(type, handler, options);
|
|
137
120
|
this._dragListeners.push({ target, type, handler, options });
|
|
138
121
|
}
|
|
139
|
-
|
|
140
122
|
_clearDragListeners() {
|
|
141
123
|
this._dragListeners.forEach(({ target, type, handler, options }) => {
|
|
142
124
|
target.removeEventListener(type, handler, options);
|
|
@@ -145,7 +127,6 @@ export default class MooSlider {
|
|
|
145
127
|
this._draggingInput = null;
|
|
146
128
|
this._element.removeAttribute("data-slider-dragging");
|
|
147
129
|
}
|
|
148
|
-
|
|
149
130
|
_bindEvents() {
|
|
150
131
|
this._inputs.forEach((input) => {
|
|
151
132
|
this._listen(input, "input", () => this._sync(input));
|
|
@@ -157,9 +138,7 @@ export default class MooSlider {
|
|
|
157
138
|
this._listen(input, "focusout", () => this._clearPointerFocus());
|
|
158
139
|
});
|
|
159
140
|
const forms = new Set(
|
|
160
|
-
this._inputs
|
|
161
|
-
.map((input) => input.form || input.closest?.("form"))
|
|
162
|
-
.filter(Boolean),
|
|
141
|
+
this._inputs.map((input) => input.form || input.closest?.("form")).filter(Boolean)
|
|
163
142
|
);
|
|
164
143
|
forms.forEach((form) => {
|
|
165
144
|
this._listen(form, "reset", () => {
|
|
@@ -168,19 +147,16 @@ export default class MooSlider {
|
|
|
168
147
|
});
|
|
169
148
|
this._listen(this._track, "pointerdown", (event) => this._handleTrackPointer(event));
|
|
170
149
|
}
|
|
171
|
-
|
|
172
150
|
_trigger(name) {
|
|
173
151
|
this._element.dispatchEvent(
|
|
174
152
|
new this._window.CustomEvent(`${name}.moo.slider`, {
|
|
175
|
-
bubbles: true
|
|
153
|
+
bubbles: true
|
|
176
154
|
})
|
|
177
155
|
);
|
|
178
156
|
}
|
|
179
|
-
|
|
180
157
|
_isRange() {
|
|
181
158
|
return this._inputs.length === 2;
|
|
182
159
|
}
|
|
183
|
-
|
|
184
160
|
_sync(changedInput = null) {
|
|
185
161
|
if (this._isRange()) {
|
|
186
162
|
const [startInput, endInput] = this._inputs;
|
|
@@ -199,34 +175,29 @@ export default class MooSlider {
|
|
|
199
175
|
this._syncAria(endInput);
|
|
200
176
|
return;
|
|
201
177
|
}
|
|
202
|
-
|
|
203
178
|
const input = this._inputs[0];
|
|
204
179
|
this._writeFill(0, valuePercent(input));
|
|
205
180
|
this._writeOutput(displayValue(input));
|
|
206
181
|
this._syncAria(input);
|
|
207
182
|
}
|
|
208
|
-
|
|
209
183
|
_syncAria(input) {
|
|
210
184
|
input.setAttribute("aria-valuemin", String(inputMinimum(input)));
|
|
211
185
|
input.setAttribute("aria-valuemax", String(inputMaximum(input)));
|
|
212
186
|
input.setAttribute("aria-valuenow", displayValue(input));
|
|
213
187
|
}
|
|
214
|
-
|
|
215
188
|
_writeFill(start, end) {
|
|
216
189
|
const clampedStart = clamp(start, 0, 100);
|
|
217
190
|
const clampedEnd = clamp(end, 0, 100);
|
|
218
191
|
this._element.style.setProperty("--moo-slider-start", `${Math.min(clampedStart, clampedEnd)}%`);
|
|
219
192
|
this._element.style.setProperty("--moo-slider-end", `${Math.max(clampedStart, clampedEnd)}%`);
|
|
220
193
|
}
|
|
221
|
-
|
|
222
194
|
_writeOutput(value) {
|
|
223
195
|
if (this._output) {
|
|
224
196
|
this._output.textContent = value;
|
|
225
197
|
}
|
|
226
198
|
}
|
|
227
|
-
|
|
228
199
|
_handleTrackPointer(event) {
|
|
229
|
-
if (event.button !==
|
|
200
|
+
if (event.button !== void 0 && event.button !== 0) {
|
|
230
201
|
return;
|
|
231
202
|
}
|
|
232
203
|
const enabledInputs = this._inputs.filter((input) => !input.disabled);
|
|
@@ -240,23 +211,19 @@ export default class MooSlider {
|
|
|
240
211
|
this._startDrag(target, event);
|
|
241
212
|
this._setInputFromPointer(target, event);
|
|
242
213
|
}
|
|
243
|
-
|
|
244
214
|
_setPointerFocus() {
|
|
245
215
|
this._element.setAttribute("data-slider-pointer-focus", "true");
|
|
246
216
|
}
|
|
247
|
-
|
|
248
217
|
_clearPointerFocus() {
|
|
249
218
|
this._element.removeAttribute("data-slider-pointer-focus");
|
|
250
219
|
}
|
|
251
|
-
|
|
252
220
|
_startDrag(input, event) {
|
|
253
221
|
this._clearDragListeners();
|
|
254
222
|
this._draggingInput = input;
|
|
255
223
|
this._element.setAttribute("data-slider-dragging", "true");
|
|
256
224
|
this._track.setPointerCapture?.(event.pointerId);
|
|
257
|
-
|
|
258
225
|
const pointerId = event.pointerId;
|
|
259
|
-
const samePointer = (nextEvent) => pointerId ===
|
|
226
|
+
const samePointer = (nextEvent) => pointerId === void 0 || nextEvent.pointerId === pointerId;
|
|
260
227
|
const onMove = (moveEvent) => {
|
|
261
228
|
if (!samePointer(moveEvent) || this._draggingInput !== input) {
|
|
262
229
|
return;
|
|
@@ -274,12 +241,10 @@ export default class MooSlider {
|
|
|
274
241
|
this._track.releasePointerCapture?.(pointerId);
|
|
275
242
|
this._clearDragListeners();
|
|
276
243
|
};
|
|
277
|
-
|
|
278
244
|
this._listenDuringDrag(this._document, "pointermove", onMove);
|
|
279
245
|
this._listenDuringDrag(this._document, "pointerup", onEnd);
|
|
280
246
|
this._listenDuringDrag(this._document, "pointercancel", onEnd);
|
|
281
247
|
}
|
|
282
|
-
|
|
283
248
|
_setInputFromPointer(input, event, emitInput = true) {
|
|
284
249
|
const percent = this._pointerPercent(event);
|
|
285
250
|
const min = inputMinimum(input);
|
|
@@ -291,7 +256,6 @@ export default class MooSlider {
|
|
|
291
256
|
input.dispatchEvent(new this._window.Event("input", { bubbles: true }));
|
|
292
257
|
}
|
|
293
258
|
}
|
|
294
|
-
|
|
295
259
|
_pointerPercent(event) {
|
|
296
260
|
const rect = this._track.getBoundingClientRect();
|
|
297
261
|
const orientation = this._element.dataset.sliderOrientation || "horizontal";
|
|
@@ -300,13 +264,11 @@ export default class MooSlider {
|
|
|
300
264
|
}
|
|
301
265
|
return this._horizontalPointerPercent(event, rect);
|
|
302
266
|
}
|
|
303
|
-
|
|
304
267
|
_horizontalPointerPercent(event, rect) {
|
|
305
268
|
const direction = this._window.getComputedStyle?.(this._element).direction;
|
|
306
269
|
const offset = direction === "rtl" ? rect.right - event.clientX : event.clientX - rect.left;
|
|
307
270
|
return clamp(offset / (rect.width || 1), 0, 1);
|
|
308
271
|
}
|
|
309
|
-
|
|
310
272
|
_nearestInput(percent, inputs) {
|
|
311
273
|
if (inputs.length === 1) {
|
|
312
274
|
return inputs[0];
|
|
@@ -322,3 +284,6 @@ export default class MooSlider {
|
|
|
322
284
|
return endDistance < startDistance ? endInput : startInput;
|
|
323
285
|
}
|
|
324
286
|
}
|
|
287
|
+
export {
|
|
288
|
+
MooSlider as default
|
|
289
|
+
};
|
package/dist/js/state.js
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Moo UI state.js v1.0.0 (https://wpmoo.org/)
|
|
3
|
+
* Copyright 2026 WPMoo Authors
|
|
4
|
+
* Licensed under MIT (https://github.com/wpmoo-org/ui/blob/main/LICENSE)
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
(() => {
|
|
8
|
+
const ownerDocument = typeof document === "undefined" ? null : document;
|
|
9
|
+
const owner = ownerDocument?.currentScript?.parentElement;
|
|
10
|
+
if (!owner) return;
|
|
11
|
+
const view = ownerDocument?.defaultView || (typeof window === "undefined" ? null : window);
|
|
12
|
+
if (owner.matches?.('.moo-ui[data-bs-theme="light"], .moo-ui[data-bs-theme="dark"]')) {
|
|
13
|
+
const body = ownerDocument?.body;
|
|
14
|
+
const documentOwner = owner.dataset?.mooDocumentOwner === "true" && owner.parentElement === body && owner === body?.firstElementChild;
|
|
15
|
+
const normalizeDirection = (value) => value === "ltr" || value === "rtl" ? value : null;
|
|
16
|
+
const ownerDirection = normalizeDirection(
|
|
17
|
+
owner.getAttribute?.("dir") || owner.dir
|
|
18
|
+
);
|
|
19
|
+
const documentDirection = normalizeDirection(
|
|
20
|
+
ownerDocument?.documentElement?.getAttribute?.("dir") || ownerDocument?.documentElement?.dir
|
|
21
|
+
);
|
|
22
|
+
owner.__mooStateBaseline = {
|
|
23
|
+
theme: owner.dataset.bsTheme === "dark" ? "dark" : "light",
|
|
24
|
+
direction: documentOwner ? documentDirection || "ltr" : ownerDirection
|
|
25
|
+
};
|
|
26
|
+
const readPreference = (axis, allowed) => {
|
|
27
|
+
const dataKey = axis === "theme" ? "mooThemeKey" : "mooDirectionKey";
|
|
28
|
+
const explicit = owner.dataset?.[dataKey]?.trim();
|
|
29
|
+
const key2 = explicit || (documentOwner ? `moo:${axis}` : null);
|
|
30
|
+
if (!key2) return null;
|
|
31
|
+
try {
|
|
32
|
+
const value = view?.localStorage?.getItem(key2);
|
|
33
|
+
return allowed.includes(value) ? value : null;
|
|
34
|
+
} catch (_) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
const systemPrefersDark = () => {
|
|
39
|
+
try {
|
|
40
|
+
const matchMedia = view?.matchMedia;
|
|
41
|
+
if (typeof matchMedia !== "function") return null;
|
|
42
|
+
return Boolean(
|
|
43
|
+
matchMedia.call(view, "(prefers-color-scheme: dark)")?.matches
|
|
44
|
+
);
|
|
45
|
+
} catch (_) {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
try {
|
|
50
|
+
const storedTheme = readPreference("theme", ["light", "dark", "system"]);
|
|
51
|
+
const mediaPrefersDark = storedTheme === "system" ? systemPrefersDark() : null;
|
|
52
|
+
const resolvedTheme = storedTheme === "dark" ? "dark" : storedTheme === "light" ? "light" : storedTheme === "system" && mediaPrefersDark !== null ? mediaPrefersDark ? "dark" : "light" : owner.dataset.bsTheme === "dark" ? "dark" : "light";
|
|
53
|
+
owner.dataset.bsTheme = resolvedTheme;
|
|
54
|
+
const storedDirection = readPreference("direction", ["ltr", "rtl"]);
|
|
55
|
+
if (storedDirection) {
|
|
56
|
+
if (documentOwner) ownerDocument.documentElement.dir = storedDirection;
|
|
57
|
+
else owner.dir = storedDirection;
|
|
58
|
+
}
|
|
59
|
+
} finally {
|
|
60
|
+
owner.dataset.mooState = "ready";
|
|
61
|
+
}
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
if (!owner.matches?.('[data-slot="sidebar-wrapper"][data-sidebar-key]')) return;
|
|
65
|
+
const key = owner.dataset?.sidebarKey;
|
|
66
|
+
if (!key) return;
|
|
67
|
+
try {
|
|
68
|
+
const state = view?.localStorage?.getItem(`moo-sidebar:${key}`);
|
|
69
|
+
if (state === "expanded" || state === "collapsed") {
|
|
70
|
+
owner.dataset.sidebarState = state;
|
|
71
|
+
}
|
|
72
|
+
} catch (_) {
|
|
73
|
+
} finally {
|
|
74
|
+
owner.dataset.sidebarStateReady = "";
|
|
75
|
+
}
|
|
76
|
+
})();
|
|
@@ -3,22 +3,22 @@
|
|
|
3
3
|
{
|
|
4
4
|
"export": "./moo.css",
|
|
5
5
|
"path": "dist/assets/css/moo.css",
|
|
6
|
-
"sha256": "
|
|
6
|
+
"sha256": "32108d9a95122382228038cd4fe4ca48736a8c0b6219375a08e7697d96d9abd3"
|
|
7
7
|
},
|
|
8
8
|
{
|
|
9
9
|
"export": "./moo-ui.css",
|
|
10
10
|
"path": "dist/assets/css/moo-ui.css",
|
|
11
|
-
"sha256": "
|
|
11
|
+
"sha256": "5824bc488463bc6e6d967e4079b30d8053c9d67cba01479c10cde3830865a1bb"
|
|
12
12
|
},
|
|
13
13
|
{
|
|
14
|
-
"export": "./
|
|
15
|
-
"path": "dist/js/
|
|
16
|
-
"sha256": "
|
|
14
|
+
"export": "./state.js",
|
|
15
|
+
"path": "dist/js/state.js",
|
|
16
|
+
"sha256": "85b12aea0f22f1a29c9ffe791b0d53d53cc7ab55b08ede10029edc558c8786a6"
|
|
17
17
|
}
|
|
18
18
|
],
|
|
19
19
|
"package": {
|
|
20
20
|
"name": "@wpmoo/ui",
|
|
21
|
-
"version": "1.0.0
|
|
21
|
+
"version": "1.0.0"
|
|
22
22
|
},
|
|
23
23
|
"schemaVersion": 1
|
|
24
24
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wpmoo/ui",
|
|
3
|
-
"version": "1.0.0
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "Bootstrap markup. shadcn feel. A frontend-framework-free component system for server-rendered apps.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "WPMoo (https://wpmoo.org)",
|
|
@@ -38,11 +38,12 @@
|
|
|
38
38
|
"./context-menu.js": "./dist/js/context-menu.js",
|
|
39
39
|
"./datatable.js": "./dist/js/datatable.js",
|
|
40
40
|
"./slider.js": "./dist/js/slider.js",
|
|
41
|
+
"./sheet.js": "./dist/js/sheet.js",
|
|
41
42
|
"./chart.js": "./dist/js/chart.js",
|
|
42
43
|
"./chart.min.js": "./dist/js/chart.min.js",
|
|
43
44
|
"./datepicker.js": "./dist/js/datepicker.js",
|
|
44
45
|
"./datepicker.min.js": "./dist/js/datepicker.min.js",
|
|
45
|
-
"./
|
|
46
|
+
"./state.js": "./dist/js/state.js",
|
|
46
47
|
"./release-manifest.json": "./dist/release-manifest.json",
|
|
47
48
|
"./scss/config": "./scss/_config.scss",
|
|
48
49
|
"./scss/moo-ui": "./scss/moo-ui.scss",
|
|
@@ -64,11 +65,12 @@
|
|
|
64
65
|
"dist/js/context-menu.js",
|
|
65
66
|
"dist/js/datatable.js",
|
|
66
67
|
"dist/js/slider.js",
|
|
68
|
+
"dist/js/sheet.js",
|
|
67
69
|
"dist/js/chart.js",
|
|
68
70
|
"dist/js/chart.min.js",
|
|
69
71
|
"dist/js/datepicker.js",
|
|
70
72
|
"dist/js/datepicker.min.js",
|
|
71
|
-
"dist/js/
|
|
73
|
+
"dist/js/state.js",
|
|
72
74
|
"dist/release-manifest.json",
|
|
73
75
|
"scss/*.scss",
|
|
74
76
|
"scss/**/*.scss",
|
package/scss/_components.scss
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
/* Bootstrap Components */
|
|
2
2
|
@import "bootstrap/scss/tables";
|
|
3
3
|
@import "bootstrap/scss/forms/labels";
|
|
4
4
|
@import "bootstrap/scss/forms/form-text";
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
@import "bootstrap/scss/offcanvas";
|
|
26
26
|
@import "bootstrap/scss/helpers/color-bg";
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
/* Moo Components */
|
|
29
29
|
@import "components/kbd";
|
|
30
30
|
@import "components/input";
|
|
31
31
|
@import "components/textarea";
|
package/scss/_config.scss
CHANGED
|
@@ -1,24 +1,18 @@
|
|
|
1
|
-
// Moo UI public Sass config
|
|
2
|
-
//
|
|
3
|
-
// Import this before Bootstrap variables so overrides take precedence.
|
|
4
|
-
//
|
|
5
|
-
// Only the variables below are public. Derived $moo-* tokens and component
|
|
6
|
-
// knobs are internal and may change without notice.
|
|
7
1
|
|
|
8
|
-
$primary: #171717 !default;
|
|
9
|
-
$secondary: #f4f4f5 !default;
|
|
10
|
-
$success: #047857 !default;
|
|
11
|
-
$info: #0369a1 !default;
|
|
12
|
-
$warning: #b45309 !default;
|
|
13
|
-
$danger: #e7000b !default;
|
|
14
|
-
$light: #fafafa !default;
|
|
15
|
-
$dark: #18181b !default;
|
|
2
|
+
$primary: #171717 !default;
|
|
3
|
+
$secondary: #f4f4f5 !default;
|
|
4
|
+
$success: #047857 !default;
|
|
5
|
+
$info: #0369a1 !default;
|
|
6
|
+
$warning: #b45309 !default;
|
|
7
|
+
$danger: #e7000b !default;
|
|
8
|
+
$light: #fafafa !default;
|
|
9
|
+
$dark: #18181b !default;
|
|
16
10
|
|
|
17
|
-
$body-color: #18181b !default;
|
|
18
|
-
$body-bg: #fff !default;
|
|
19
|
-
$font-size-base: 0.875rem !default;
|
|
11
|
+
$body-color: #18181b !default;
|
|
12
|
+
$body-bg: #fff !default;
|
|
13
|
+
$font-size-base: 0.875rem !default;
|
|
20
14
|
|
|
21
|
-
$border-color: #e4e4e7 !default;
|
|
22
|
-
$border-radius: 0.5rem !default;
|
|
23
|
-
$border-radius-sm: 0.375rem !default;
|
|
24
|
-
$border-radius-lg: 0.625rem !default;
|
|
15
|
+
$border-color: #e4e4e7 !default;
|
|
16
|
+
$border-radius: 0.5rem !default;
|
|
17
|
+
$border-radius-sm: 0.375rem !default;
|
|
18
|
+
$border-radius-lg: 0.625rem !default;
|
package/scss/_settings.scss
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
// Ordered Sass settings aggregate. These partials emit variables only; preserve
|
|
2
|
-
// this sequence because later component and catalog knobs depend on earlier
|
|
3
|
-
// palette and form values before Bootstrap's own defaults are loaded.
|
|
4
1
|
@import "config";
|
|
5
2
|
@import "settings/palette";
|
|
6
3
|
@import "settings/forms";
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
// on expand, not Bootstrap's baked-in ::after background-image glyph.
|
|
3
|
-
// Render the same icon our other components use and drive the rotation
|
|
4
|
-
// off Bootstrap's own :not(.collapsed) state hook instead.
|
|
1
|
+
/* Accordion */
|
|
5
2
|
.accordion-button::after {
|
|
6
3
|
content: none;
|
|
7
4
|
}
|
|
@@ -27,8 +24,6 @@
|
|
|
27
24
|
text-align: start;
|
|
28
25
|
}
|
|
29
26
|
|
|
30
|
-
// The reference trigger has no active/pressed background — only a hover
|
|
31
|
-
// underline signals interactivity, matching a plain text-link affordance.
|
|
32
27
|
.accordion-button:hover {
|
|
33
28
|
text-decoration: underline;
|
|
34
29
|
}
|
|
@@ -43,10 +38,6 @@
|
|
|
43
38
|
text-decoration: none;
|
|
44
39
|
}
|
|
45
40
|
|
|
46
|
-
// The reference's flush trigger and body sit edge-to-edge with no
|
|
47
|
-
// horizontal padding, and the trigger reads as medium weight, not
|
|
48
|
-
// Bootstrap's own regular default -- both retune existing Bootstrap
|
|
49
|
-
// accordion tokens/properties, not new selectors.
|
|
50
41
|
.accordion-flush {
|
|
51
42
|
--bs-accordion-btn-padding-x: 0;
|
|
52
43
|
--bs-accordion-btn-padding-y: #{$spacer * 0.625};
|
|
@@ -58,8 +49,6 @@
|
|
|
58
49
|
font-weight: $font-weight-medium;
|
|
59
50
|
}
|
|
60
51
|
|
|
61
|
-
// A card owns its own surface, so a nested accordion must let that surface
|
|
62
|
-
// show through instead of painting Bootstrap's body background on top of it.
|
|
63
52
|
.card .accordion {
|
|
64
53
|
--bs-accordion-bg: #{$moo-accordion-contained-bg};
|
|
65
54
|
}
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
// .alert-{state} modifier sets them; the design reference's quiet style
|
|
3
|
-
// keeps a visible neutral border even on the unmodified/default alert.
|
|
1
|
+
/* Alert */
|
|
4
2
|
$moo-alert-dismissible-close-space: $btn-close-width + ($btn-close-padding-x * 2) + 0.5rem !default;
|
|
5
3
|
|
|
6
4
|
.alert {
|
|
@@ -29,21 +27,12 @@ $moo-alert-dismissible-close-space: $btn-close-width + ($btn-close-padding-x * 2
|
|
|
29
27
|
padding: $btn-close-padding-y $btn-close-padding-x;
|
|
30
28
|
}
|
|
31
29
|
|
|
32
|
-
// The reference's destructive alert keeps the same neutral surface and
|
|
33
|
-
// border as the default alert and tints only the text/icon color —
|
|
34
|
-
// verified against the live reference page's Destructive example (bg-card,
|
|
35
|
-
// text-destructive). Bootstrap's own alert-danger class instead fills a
|
|
36
|
-
// saturated subtle-danger background, so re-anchor its consumption
|
|
37
|
-
// variables back to the neutral ones and layer only the color shift on top.
|
|
38
30
|
.alert-danger {
|
|
39
31
|
--bs-alert-bg: transparent;
|
|
40
32
|
--bs-alert-border-color: var(--moo-border);
|
|
41
33
|
--bs-alert-color: var(--moo-destructive);
|
|
42
34
|
}
|
|
43
35
|
|
|
44
|
-
// Warning and success alerts follow the same quiet pattern as destructive:
|
|
45
|
-
// neutral border, tinted alpha surface, hue-colored text. Matches the
|
|
46
|
-
// reference's alert variants (amber for warning, green for success).
|
|
47
36
|
.alert-warning {
|
|
48
37
|
--bs-alert-bg: var(--moo-warning-surface);
|
|
49
38
|
--bs-alert-border-color: var(--moo-border);
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
// intentionally small and consumes the shared Bootstrap radius/border primitives.
|
|
1
|
+
/* Avatar */
|
|
3
2
|
.avatar {
|
|
4
3
|
position: relative;
|
|
5
4
|
display: inline-flex;
|
|
@@ -8,9 +7,6 @@
|
|
|
8
7
|
width: $avatar-size;
|
|
9
8
|
height: $avatar-size;
|
|
10
9
|
flex: 0 0 auto;
|
|
11
|
-
// A badge (such as a presence dot) sits at the avatar's corner and must
|
|
12
|
-
// stay visible outside the circle; the image/fallback clip to the circle
|
|
13
|
-
// on their own, so the root itself does not need to clip its children.
|
|
14
10
|
overflow: visible;
|
|
15
11
|
border: 0;
|
|
16
12
|
border-radius: var(--bs-border-radius-pill);
|
|
@@ -66,10 +62,6 @@
|
|
|
66
62
|
padding-inline: 0.2rem;
|
|
67
63
|
border: 0;
|
|
68
64
|
border-radius: var(--bs-border-radius-pill);
|
|
69
|
-
// Mirrors the reference's ring-2 treatment: the badge keeps its own
|
|
70
|
-
// 10px/12px/15px box while the page-background ring paints outside it.
|
|
71
|
-
// box-shadow (not border) keeps the ring out of the layout box, matching
|
|
72
|
-
// the .avatar-group ring below and Tailwind's own ring-* technique.
|
|
73
65
|
box-shadow: $avatar-badge-ring-shadow;
|
|
74
66
|
background-color: var(--moo-muted-surface);
|
|
75
67
|
color: var(--moo-foreground);
|
|
@@ -83,9 +75,6 @@
|
|
|
83
75
|
height: 0.625rem;
|
|
84
76
|
}
|
|
85
77
|
|
|
86
|
-
// A plain presence/status dot (no text or icon content) -- the reference's
|
|
87
|
-
// own AvatarBadge with no children, recolored per use via badge_class
|
|
88
|
-
// (such as a Bootstrap bg-success utility) rather than a hardcoded color here.
|
|
89
78
|
.avatar-badge--dot {
|
|
90
79
|
height: $avatar-badge-dot-size;
|
|
91
80
|
min-width: $avatar-badge-dot-size;
|
|
@@ -121,10 +110,6 @@
|
|
|
121
110
|
align-items: center;
|
|
122
111
|
}
|
|
123
112
|
|
|
124
|
-
// Matches the reference's ring-2 ring-background: each avatar in a group
|
|
125
|
-
// carries a page-background ring (light = white, dark = black) so stacked
|
|
126
|
-
// avatars stay visibly separated. --bs-body-bg is theme-aware in both the
|
|
127
|
-
// standalone and scoped builds, mirroring the badge ring treatment.
|
|
128
113
|
.avatar-group > .avatar {
|
|
129
114
|
box-shadow: $avatar-group-ring-shadow;
|
|
130
115
|
z-index: 0;
|