@ponchia/ui 0.3.4 → 0.3.6
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/README.md +121 -175
- package/behaviors/index.d.ts +27 -0
- package/behaviors/index.js +305 -0
- package/classes/index.d.ts +41 -0
- package/classes/index.js +41 -0
- package/css/disclosure.css +180 -0
- package/css/dots.css +42 -4
- package/css/feedback.css +111 -0
- package/css/forms.css +44 -0
- package/css/overlay.css +48 -0
- package/css/primitives.css +60 -0
- package/css/site.css +33 -0
- package/dist/bronto.css +1 -1
- package/dist/css/disclosure.css +1 -1
- package/dist/css/dots.css +1 -1
- package/dist/css/feedback.css +1 -1
- package/dist/css/forms.css +1 -1
- package/dist/css/overlay.css +1 -1
- package/dist/css/primitives.css +1 -1
- package/dist/css/site.css +1 -1
- package/docs/reference.md +73 -1
- package/docs/usage.md +110 -0
- package/fonts/OFL.txt +93 -0
- package/glyphs/glyphs.d.ts +102 -0
- package/glyphs/glyphs.js +922 -0
- package/llms.txt +11 -0
- package/package.json +28 -4
package/behaviors/index.js
CHANGED
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
* const stop = initThemeToggle(); // wire [data-bronto-theme-toggle]
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
+
import { GLYPH_SIZE, glyphCells } from '../glyphs/glyphs.js';
|
|
18
|
+
|
|
17
19
|
const THEMES = ['light', 'dark'];
|
|
18
20
|
const noop = () => {};
|
|
19
21
|
const hasDom = () => typeof document !== 'undefined';
|
|
@@ -1044,3 +1046,306 @@ export function initTableSort({ root } = {}) {
|
|
|
1044
1046
|
|
|
1045
1047
|
return () => cleanups.forEach((fn) => fn());
|
|
1046
1048
|
}
|
|
1049
|
+
|
|
1050
|
+
/**
|
|
1051
|
+
* Image carousel / gallery, built on CSS scroll-snap so touch + trackpad
|
|
1052
|
+
* swipe (and momentum) are the browser's, not hand-rolled. This wires the
|
|
1053
|
+
* parts scroll-snap can't do alone: prev/next buttons, keyboard nav, a
|
|
1054
|
+
* thumbnail strip, the position counter, and ARIA — keeping a JS index in
|
|
1055
|
+
* sync with the scroll position both ways.
|
|
1056
|
+
*
|
|
1057
|
+
* Markup: `[data-bronto-carousel]` containing a `.ui-carousel__viewport`
|
|
1058
|
+
* of `.ui-carousel__slide` children; optionally
|
|
1059
|
+
* `[data-bronto-carousel-prev]` / `[data-bronto-carousel-next]` controls,
|
|
1060
|
+
* a `.ui-carousel__thumbs` list of `.ui-carousel__thumb` buttons, and a
|
|
1061
|
+
* `.ui-carousel__status` counter slot. Add `data-bronto-carousel-loop` to
|
|
1062
|
+
* wrap at the ends, `data-bronto-carousel-label` to name the region.
|
|
1063
|
+
*
|
|
1064
|
+
* A full-screen **lightbox** is the same markup inside a native
|
|
1065
|
+
* `<dialog class="ui-lightbox">` opened by {@link initDialog}: the
|
|
1066
|
+
* `<dialog>` provides the top layer, focus-trap, Escape and focus-return,
|
|
1067
|
+
* so this behavior never touches focus management.
|
|
1068
|
+
*
|
|
1069
|
+
* Emits `bronto:change` ({ detail: { index } }) on every index change
|
|
1070
|
+
* (button, key, thumbnail, or swipe). SSR-safe, idempotent per carousel;
|
|
1071
|
+
* returns a cleanup function.
|
|
1072
|
+
*/
|
|
1073
|
+
export function initCarousel({ root } = {}) {
|
|
1074
|
+
if (!hasDom()) return noop;
|
|
1075
|
+
const host = root || document;
|
|
1076
|
+
const boxes = [];
|
|
1077
|
+
if (host !== document && host.matches?.('[data-bronto-carousel]')) boxes.push(host);
|
|
1078
|
+
boxes.push(...(host.querySelectorAll?.('[data-bronto-carousel]') ?? []));
|
|
1079
|
+
const cleanups = [];
|
|
1080
|
+
|
|
1081
|
+
for (const box of boxes) {
|
|
1082
|
+
const viewport = box.querySelector('.ui-carousel__viewport');
|
|
1083
|
+
if (!viewport) continue;
|
|
1084
|
+
const slides = [...viewport.children].filter((el) =>
|
|
1085
|
+
el.classList.contains('ui-carousel__slide'),
|
|
1086
|
+
);
|
|
1087
|
+
if (!slides.length) continue;
|
|
1088
|
+
const n = slides.length;
|
|
1089
|
+
const thumbs = [...box.querySelectorAll('.ui-carousel__thumb')];
|
|
1090
|
+
const status = box.querySelector('.ui-carousel__status');
|
|
1091
|
+
const prevBtn = box.querySelector('[data-bronto-carousel-prev]');
|
|
1092
|
+
const nextBtn = box.querySelector('[data-bronto-carousel-next]');
|
|
1093
|
+
const loop = box.hasAttribute('data-bronto-carousel-loop');
|
|
1094
|
+
|
|
1095
|
+
// ARIA scaffolding — pragmatic carousel semantics (not the full APG
|
|
1096
|
+
// tablist), the same restraint initMenu takes.
|
|
1097
|
+
viewport.setAttribute('role', 'group');
|
|
1098
|
+
viewport.setAttribute('aria-roledescription', 'carousel');
|
|
1099
|
+
if (!viewport.hasAttribute('aria-label'))
|
|
1100
|
+
viewport.setAttribute(
|
|
1101
|
+
'aria-label',
|
|
1102
|
+
box.getAttribute('data-bronto-carousel-label') || 'Carousel',
|
|
1103
|
+
);
|
|
1104
|
+
if (!viewport.hasAttribute('tabindex')) viewport.tabIndex = 0;
|
|
1105
|
+
slides.forEach((s, i) => {
|
|
1106
|
+
s.setAttribute('role', 'group');
|
|
1107
|
+
s.setAttribute('aria-roledescription', 'slide');
|
|
1108
|
+
if (!s.hasAttribute('aria-label')) s.setAttribute('aria-label', `${i + 1} of ${n}`);
|
|
1109
|
+
});
|
|
1110
|
+
if (status) status.setAttribute('aria-live', 'polite');
|
|
1111
|
+
for (const b of [prevBtn, nextBtn]) {
|
|
1112
|
+
if (!b) continue;
|
|
1113
|
+
if (b.tagName === 'BUTTON' && !b.hasAttribute('type')) b.type = 'button';
|
|
1114
|
+
}
|
|
1115
|
+
if (prevBtn && !prevBtn.hasAttribute('aria-label'))
|
|
1116
|
+
prevBtn.setAttribute('aria-label', 'Previous');
|
|
1117
|
+
if (nextBtn && !nextBtn.hasAttribute('aria-label')) nextBtn.setAttribute('aria-label', 'Next');
|
|
1118
|
+
|
|
1119
|
+
let index = Math.max(
|
|
1120
|
+
0,
|
|
1121
|
+
slides.findIndex((s) => s.hasAttribute('data-bronto-carousel-current')),
|
|
1122
|
+
);
|
|
1123
|
+
|
|
1124
|
+
// While a button/keyboard nav is smooth-scrolling, the IntersectionObserver
|
|
1125
|
+
// would observe the intermediate slides crossing its threshold and re-fire
|
|
1126
|
+
// `bronto:change` for each — a feedback burst on a single Home→End jump.
|
|
1127
|
+
// This flag makes the IO drive the index on *user* swipes only; a timeout
|
|
1128
|
+
// (not the patchy `scrollend` event) releases it once the scroll settles.
|
|
1129
|
+
let programmatic = false;
|
|
1130
|
+
let progTimer = null;
|
|
1131
|
+
const holdProgrammatic = () => {
|
|
1132
|
+
programmatic = true;
|
|
1133
|
+
if (progTimer) clearTimeout(progTimer);
|
|
1134
|
+
progTimer = setTimeout(() => {
|
|
1135
|
+
programmatic = false;
|
|
1136
|
+
}, 500);
|
|
1137
|
+
progTimer?.unref?.(); // don't keep a Node test process alive
|
|
1138
|
+
};
|
|
1139
|
+
|
|
1140
|
+
const render = () => {
|
|
1141
|
+
if (status) status.textContent = `${index + 1} / ${n}`;
|
|
1142
|
+
thumbs.forEach((t, i) => {
|
|
1143
|
+
if (i === index) t.setAttribute('aria-current', 'true');
|
|
1144
|
+
else t.removeAttribute('aria-current');
|
|
1145
|
+
});
|
|
1146
|
+
if (prevBtn && !loop) prevBtn.disabled = index === 0;
|
|
1147
|
+
if (nextBtn && !loop) nextBtn.disabled = index === n - 1;
|
|
1148
|
+
};
|
|
1149
|
+
|
|
1150
|
+
const emit = () =>
|
|
1151
|
+
box.dispatchEvent(new CustomEvent('bronto:change', { detail: { index }, bubbles: true }));
|
|
1152
|
+
|
|
1153
|
+
// jsdom (and any layout-less env) has no scrollIntoView; it's a pure
|
|
1154
|
+
// affordance, so never let it break index/aria sync — same guard as
|
|
1155
|
+
// initCombobox.
|
|
1156
|
+
const reveal = (el) => {
|
|
1157
|
+
try {
|
|
1158
|
+
el?.scrollIntoView({ block: 'nearest', inline: 'center' });
|
|
1159
|
+
} catch {
|
|
1160
|
+
/* no layout — ignore */
|
|
1161
|
+
}
|
|
1162
|
+
};
|
|
1163
|
+
|
|
1164
|
+
const goTo = (i, { emitChange = true } = {}) => {
|
|
1165
|
+
const next = loop ? (i + n) % n : Math.max(0, Math.min(n - 1, i));
|
|
1166
|
+
const changed = next !== index;
|
|
1167
|
+
index = next;
|
|
1168
|
+
holdProgrammatic(); // suppress IO echo from the smooth-scroll this triggers
|
|
1169
|
+
reveal(slides[index]);
|
|
1170
|
+
reveal(thumbs[index]);
|
|
1171
|
+
render();
|
|
1172
|
+
if (changed && emitChange) emit();
|
|
1173
|
+
};
|
|
1174
|
+
|
|
1175
|
+
const onKey = (e) => {
|
|
1176
|
+
let target = null;
|
|
1177
|
+
if (e.key === 'ArrowRight') target = index + 1;
|
|
1178
|
+
else if (e.key === 'ArrowLeft') target = index - 1;
|
|
1179
|
+
else if (e.key === 'Home') target = 0;
|
|
1180
|
+
else if (e.key === 'End') target = n - 1;
|
|
1181
|
+
else return;
|
|
1182
|
+
e.preventDefault();
|
|
1183
|
+
goTo(target);
|
|
1184
|
+
};
|
|
1185
|
+
const onClick = (e) => {
|
|
1186
|
+
if (prevBtn && e.target.closest('[data-bronto-carousel-prev]')) {
|
|
1187
|
+
goTo(index - 1);
|
|
1188
|
+
return;
|
|
1189
|
+
}
|
|
1190
|
+
if (nextBtn && e.target.closest('[data-bronto-carousel-next]')) {
|
|
1191
|
+
goTo(index + 1);
|
|
1192
|
+
return;
|
|
1193
|
+
}
|
|
1194
|
+
const thumb = e.target.closest('.ui-carousel__thumb');
|
|
1195
|
+
if (thumb) {
|
|
1196
|
+
const i = thumbs.indexOf(thumb);
|
|
1197
|
+
if (i >= 0) goTo(i);
|
|
1198
|
+
}
|
|
1199
|
+
};
|
|
1200
|
+
|
|
1201
|
+
// Swipe sync (enhancement): when the user scrolls the viewport, snap
|
|
1202
|
+
// the JS index to the slide that's settled into view. Feature-detected
|
|
1203
|
+
// so the buttons/keyboard still work where IntersectionObserver is
|
|
1204
|
+
// absent (jsdom, older engines).
|
|
1205
|
+
let io = null;
|
|
1206
|
+
if (typeof IntersectionObserver === 'function') {
|
|
1207
|
+
io = new IntersectionObserver(
|
|
1208
|
+
(entries) => {
|
|
1209
|
+
if (programmatic) return; // ignore the echo of a button/key-driven scroll
|
|
1210
|
+
let best = null;
|
|
1211
|
+
for (const ent of entries) {
|
|
1212
|
+
if (ent.isIntersecting && (!best || ent.intersectionRatio > best.intersectionRatio))
|
|
1213
|
+
best = ent;
|
|
1214
|
+
}
|
|
1215
|
+
if (!best) return;
|
|
1216
|
+
const i = slides.indexOf(best.target);
|
|
1217
|
+
if (i >= 0 && i !== index) {
|
|
1218
|
+
index = i;
|
|
1219
|
+
render();
|
|
1220
|
+
reveal(thumbs[index]);
|
|
1221
|
+
emit();
|
|
1222
|
+
}
|
|
1223
|
+
},
|
|
1224
|
+
{ root: viewport, threshold: 0.6 },
|
|
1225
|
+
);
|
|
1226
|
+
slides.forEach((s) => io.observe(s));
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1229
|
+
render();
|
|
1230
|
+
const bound = bindOnce(box, 'carousel', () => {
|
|
1231
|
+
viewport.addEventListener('keydown', onKey);
|
|
1232
|
+
box.addEventListener('click', onClick);
|
|
1233
|
+
return () => {
|
|
1234
|
+
viewport.removeEventListener('keydown', onKey);
|
|
1235
|
+
box.removeEventListener('click', onClick);
|
|
1236
|
+
io?.disconnect();
|
|
1237
|
+
if (progTimer) clearTimeout(progTimer);
|
|
1238
|
+
};
|
|
1239
|
+
});
|
|
1240
|
+
cleanups.push(bound);
|
|
1241
|
+
}
|
|
1242
|
+
|
|
1243
|
+
return () => cleanups.forEach((fn) => fn());
|
|
1244
|
+
}
|
|
1245
|
+
|
|
1246
|
+
function restoreAttr(el, name, prev) {
|
|
1247
|
+
if (prev === null) el.removeAttribute(name);
|
|
1248
|
+
else el.setAttribute(name, prev);
|
|
1249
|
+
}
|
|
1250
|
+
|
|
1251
|
+
/**
|
|
1252
|
+
* Expand `[data-bronto-glyph="name"]` placeholders into a `.ui-dotmatrix`
|
|
1253
|
+
* grid of GLYPH_SIZE² cells — the DOM counterpart to renderGlyph() from
|
|
1254
|
+
* `@ponchia/ui/glyphs`, for when you'd rather drop a placeholder than inline
|
|
1255
|
+
* the markup. Decorative by default (`aria-hidden`); add
|
|
1256
|
+
* `data-bronto-glyph-label` to expose it as `role="img"`. An unknown glyph
|
|
1257
|
+
* name is left untouched. Idempotent (skips an already-expanded host); the
|
|
1258
|
+
* returned cleanup removes the cells and restores the original attributes.
|
|
1259
|
+
*/
|
|
1260
|
+
export function initDotGlyph({ root } = {}) {
|
|
1261
|
+
if (!hasDom()) return noop;
|
|
1262
|
+
const host = root || document;
|
|
1263
|
+
const els = [];
|
|
1264
|
+
if (host !== document && host.matches?.('[data-bronto-glyph]')) els.push(host);
|
|
1265
|
+
els.push(...(host.querySelectorAll?.('[data-bronto-glyph]') ?? []));
|
|
1266
|
+
const cleanups = [];
|
|
1267
|
+
|
|
1268
|
+
for (const el of els) {
|
|
1269
|
+
// Scope to DIRECT-child cells (the ones we append) — so a placeholder that
|
|
1270
|
+
// legitimately nests its own .ui-dotmatrix is neither mis-read as already
|
|
1271
|
+
// expanded here nor have its inner cells removed by cleanup below.
|
|
1272
|
+
if (el.querySelector(':scope > .ui-dotmatrix__cell')) continue; // already expanded
|
|
1273
|
+
const cells = glyphCells(el.getAttribute('data-bronto-glyph'));
|
|
1274
|
+
if (!cells.length) continue; // unknown glyph — leave the placeholder as-is
|
|
1275
|
+
|
|
1276
|
+
const label = el.getAttribute('data-bronto-glyph-label');
|
|
1277
|
+
// `data-bronto-glyph-solid` → square, gapless pixel glyph (legible small),
|
|
1278
|
+
// the DOM counterpart to renderGlyph's `solid` option. Implies glyph-only.
|
|
1279
|
+
const solid = el.hasAttribute('data-bronto-glyph-solid');
|
|
1280
|
+
// `data-bronto-glyph-anim="reveal|pulse"` → decorative animation (the DOM
|
|
1281
|
+
// counterpart to renderGlyph's `anim`; reduced-motion-safe via CSS).
|
|
1282
|
+
const animAttr = el.getAttribute('data-bronto-glyph-anim');
|
|
1283
|
+
const animClass =
|
|
1284
|
+
animAttr === 'reveal'
|
|
1285
|
+
? 'ui-dotmatrix--reveal'
|
|
1286
|
+
: animAttr === 'pulse'
|
|
1287
|
+
? 'ui-dotmatrix--pulse'
|
|
1288
|
+
: null;
|
|
1289
|
+
const hadAnimClass = animClass ? el.classList.contains(animClass) : false;
|
|
1290
|
+
const hadMatrix = el.classList.contains('ui-dotmatrix');
|
|
1291
|
+
const hadCols = el.style.getPropertyValue('--dotmatrix-cols');
|
|
1292
|
+
const hadRadius = el.style.getPropertyValue('--dotmatrix-dot-radius');
|
|
1293
|
+
const hadGap = el.style.getPropertyValue('--dotmatrix-gap');
|
|
1294
|
+
const hadAriaHidden = el.getAttribute('aria-hidden');
|
|
1295
|
+
const hadRole = el.getAttribute('role');
|
|
1296
|
+
const hadAriaLabel = el.getAttribute('aria-label');
|
|
1297
|
+
|
|
1298
|
+
el.classList.add('ui-dotmatrix');
|
|
1299
|
+
if (animClass) el.classList.add(animClass);
|
|
1300
|
+
el.style.setProperty('--dotmatrix-cols', String(GLYPH_SIZE));
|
|
1301
|
+
if (solid) {
|
|
1302
|
+
el.style.setProperty('--dotmatrix-dot-radius', '0');
|
|
1303
|
+
el.style.setProperty('--dotmatrix-gap', '0');
|
|
1304
|
+
}
|
|
1305
|
+
if (label) {
|
|
1306
|
+
el.setAttribute('role', 'img');
|
|
1307
|
+
el.setAttribute('aria-label', label);
|
|
1308
|
+
el.removeAttribute('aria-hidden'); // a labelled img must not also be hidden
|
|
1309
|
+
} else {
|
|
1310
|
+
el.setAttribute('aria-hidden', 'true');
|
|
1311
|
+
}
|
|
1312
|
+
|
|
1313
|
+
const frag = document.createDocumentFragment();
|
|
1314
|
+
cells.forEach((c, i) => {
|
|
1315
|
+
const span = document.createElement('span');
|
|
1316
|
+
span.className = !c.on
|
|
1317
|
+
? 'ui-dotmatrix__cell'
|
|
1318
|
+
: c.tone === 'hot'
|
|
1319
|
+
? 'ui-dotmatrix__cell ui-dotmatrix__cell--hot'
|
|
1320
|
+
: c.tone === 'accent'
|
|
1321
|
+
? 'ui-dotmatrix__cell ui-dotmatrix__cell--accent'
|
|
1322
|
+
: 'ui-dotmatrix__cell';
|
|
1323
|
+
if (!c.on && solid) span.style.background = 'transparent'; // glyph-only
|
|
1324
|
+
if (animAttr === 'reveal') span.style.setProperty('--i', String(i)); // scan stagger
|
|
1325
|
+
frag.appendChild(span);
|
|
1326
|
+
});
|
|
1327
|
+
el.appendChild(frag);
|
|
1328
|
+
|
|
1329
|
+
cleanups.push(() => {
|
|
1330
|
+
el.querySelectorAll(':scope > .ui-dotmatrix__cell').forEach((n) => n.remove());
|
|
1331
|
+
if (!hadMatrix) el.classList.remove('ui-dotmatrix');
|
|
1332
|
+
if (animClass && !hadAnimClass) el.classList.remove(animClass);
|
|
1333
|
+
if (solid) {
|
|
1334
|
+
if (hadRadius) el.style.setProperty('--dotmatrix-dot-radius', hadRadius);
|
|
1335
|
+
else el.style.removeProperty('--dotmatrix-dot-radius');
|
|
1336
|
+
if (hadGap) el.style.setProperty('--dotmatrix-gap', hadGap);
|
|
1337
|
+
else el.style.removeProperty('--dotmatrix-gap');
|
|
1338
|
+
}
|
|
1339
|
+
if (hadCols) el.style.setProperty('--dotmatrix-cols', hadCols);
|
|
1340
|
+
else el.style.removeProperty('--dotmatrix-cols');
|
|
1341
|
+
restoreAttr(el, 'aria-hidden', hadAriaHidden);
|
|
1342
|
+
restoreAttr(el, 'role', hadRole);
|
|
1343
|
+
restoreAttr(el, 'aria-label', hadAriaLabel);
|
|
1344
|
+
// Don't leave behind empty class=""/style="" we ourselves created.
|
|
1345
|
+
if (el.getAttribute('class') === '') el.removeAttribute('class');
|
|
1346
|
+
if (el.getAttribute('style') === '') el.removeAttribute('style');
|
|
1347
|
+
});
|
|
1348
|
+
}
|
|
1349
|
+
|
|
1350
|
+
return () => cleanups.forEach((fn) => fn());
|
|
1351
|
+
}
|
package/classes/index.d.ts
CHANGED
|
@@ -63,6 +63,8 @@ export declare const cls: {
|
|
|
63
63
|
readonly dotmatrixCell: 'ui-dotmatrix__cell';
|
|
64
64
|
readonly dotmatrixCellHot: 'ui-dotmatrix__cell--hot';
|
|
65
65
|
readonly dotmatrixCellAccent: 'ui-dotmatrix__cell--accent';
|
|
66
|
+
readonly dotmatrixReveal: 'ui-dotmatrix--reveal';
|
|
67
|
+
readonly dotmatrixPulse: 'ui-dotmatrix--pulse';
|
|
66
68
|
readonly dotfield: 'ui-dotfield';
|
|
67
69
|
readonly dotrule: 'ui-dotrule';
|
|
68
70
|
readonly dotbar: 'ui-dotbar';
|
|
@@ -85,6 +87,9 @@ export declare const cls: {
|
|
|
85
87
|
readonly hintError: 'ui-hint--error';
|
|
86
88
|
readonly inputGroup: 'ui-input-group';
|
|
87
89
|
readonly inputGroupAddon: 'ui-input-group__addon';
|
|
90
|
+
readonly inputIcon: 'ui-input-icon';
|
|
91
|
+
readonly inputIconSlot: 'ui-input-icon__icon';
|
|
92
|
+
readonly inputIconEnd: 'ui-input-icon--end';
|
|
88
93
|
readonly file: 'ui-file';
|
|
89
94
|
readonly range: 'ui-range';
|
|
90
95
|
readonly errorSummary: 'ui-error-summary';
|
|
@@ -115,6 +120,15 @@ export declare const cls: {
|
|
|
115
120
|
readonly progress: 'ui-progress';
|
|
116
121
|
readonly progressBar: 'ui-progress__bar';
|
|
117
122
|
readonly progressIndeterminate: 'ui-progress--indeterminate';
|
|
123
|
+
readonly meter: 'ui-meter';
|
|
124
|
+
readonly meterFill: 'ui-meter__fill';
|
|
125
|
+
readonly meterAccent: 'ui-meter--accent';
|
|
126
|
+
readonly meterSuccess: 'ui-meter--success';
|
|
127
|
+
readonly meterWarning: 'ui-meter--warning';
|
|
128
|
+
readonly meterDanger: 'ui-meter--danger';
|
|
129
|
+
readonly steps: 'ui-steps';
|
|
130
|
+
readonly stepsItem: 'ui-steps__item';
|
|
131
|
+
readonly stepsItemDone: 'ui-steps__item--done';
|
|
118
132
|
readonly modal: 'ui-modal';
|
|
119
133
|
readonly modalHead: 'ui-modal__head';
|
|
120
134
|
readonly modalTitle: 'ui-modal__title';
|
|
@@ -132,6 +146,8 @@ export declare const cls: {
|
|
|
132
146
|
readonly comboboxList: 'ui-combobox__list';
|
|
133
147
|
readonly comboboxOption: 'ui-combobox__option';
|
|
134
148
|
readonly comboboxEmpty: 'ui-combobox__empty';
|
|
149
|
+
readonly lightbox: 'ui-lightbox';
|
|
150
|
+
readonly lightboxClose: 'ui-lightbox__close';
|
|
135
151
|
readonly tabs: 'ui-tabs';
|
|
136
152
|
readonly tabsList: 'ui-tabs__list';
|
|
137
153
|
readonly tab: 'ui-tab';
|
|
@@ -150,6 +166,15 @@ export declare const cls: {
|
|
|
150
166
|
readonly avatarSm: 'ui-avatar--sm';
|
|
151
167
|
readonly avatarLg: 'ui-avatar--lg';
|
|
152
168
|
readonly avatarGroup: 'ui-avatar-group';
|
|
169
|
+
readonly carousel: 'ui-carousel';
|
|
170
|
+
readonly carouselStage: 'ui-carousel__stage';
|
|
171
|
+
readonly carouselViewport: 'ui-carousel__viewport';
|
|
172
|
+
readonly carouselSlide: 'ui-carousel__slide';
|
|
173
|
+
readonly carouselPrev: 'ui-carousel__prev';
|
|
174
|
+
readonly carouselNext: 'ui-carousel__next';
|
|
175
|
+
readonly carouselStatus: 'ui-carousel__status';
|
|
176
|
+
readonly carouselThumbs: 'ui-carousel__thumbs';
|
|
177
|
+
readonly carouselThumb: 'ui-carousel__thumb';
|
|
153
178
|
readonly table: 'ui-table';
|
|
154
179
|
readonly tableDense: 'ui-table--dense';
|
|
155
180
|
readonly tableComfortable: 'ui-table--comfortable';
|
|
@@ -190,6 +215,9 @@ export declare const cls: {
|
|
|
190
215
|
readonly siteheaderSticky: 'ui-siteheader--sticky';
|
|
191
216
|
readonly siteheaderBrand: 'ui-siteheader__brand';
|
|
192
217
|
readonly siteheaderActions: 'ui-siteheader__actions';
|
|
218
|
+
readonly pagehead: 'ui-pagehead';
|
|
219
|
+
readonly pageheadTitle: 'ui-pagehead__title';
|
|
220
|
+
readonly pageheadActions: 'ui-pagehead__actions';
|
|
193
221
|
readonly sitenav: 'ui-sitenav';
|
|
194
222
|
readonly sitemenu: 'ui-sitemenu';
|
|
195
223
|
readonly sitemenuPanel: 'ui-sitemenu__panel';
|
|
@@ -200,6 +228,10 @@ export declare const cls: {
|
|
|
200
228
|
readonly tagAccent: 'ui-tag--accent';
|
|
201
229
|
readonly meta: 'ui-meta';
|
|
202
230
|
readonly metaItem: 'ui-meta__item';
|
|
231
|
+
readonly timeline: 'ui-timeline';
|
|
232
|
+
readonly timelineItem: 'ui-timeline__item';
|
|
233
|
+
readonly timelineTime: 'ui-timeline__time';
|
|
234
|
+
readonly kbd: 'ui-kbd';
|
|
203
235
|
readonly display: 'ui-display';
|
|
204
236
|
readonly mono: 'ui-mono';
|
|
205
237
|
readonly muted: 'ui-muted';
|
|
@@ -307,6 +339,9 @@ export interface ToastOpts {
|
|
|
307
339
|
export interface ProgressOpts {
|
|
308
340
|
indeterminate?: boolean;
|
|
309
341
|
}
|
|
342
|
+
export interface MeterOpts {
|
|
343
|
+
tone?: 'accent' | 'success' | 'warning' | 'danger';
|
|
344
|
+
}
|
|
310
345
|
export interface DotspinnerOpts {
|
|
311
346
|
size?: 'sm' | 'lg';
|
|
312
347
|
}
|
|
@@ -334,6 +369,10 @@ export interface ContainerOpts {
|
|
|
334
369
|
export interface TagOpts {
|
|
335
370
|
accent?: boolean;
|
|
336
371
|
}
|
|
372
|
+
export interface InputIconOpts {
|
|
373
|
+
/** Place the icon at the inline-end instead of the start. */
|
|
374
|
+
end?: boolean;
|
|
375
|
+
}
|
|
337
376
|
|
|
338
377
|
export interface Ui {
|
|
339
378
|
button(opts?: ButtonOpts): string;
|
|
@@ -352,6 +391,7 @@ export interface Ui {
|
|
|
352
391
|
alert(opts?: AlertOpts): string;
|
|
353
392
|
toast(opts?: ToastOpts): string;
|
|
354
393
|
progress(opts?: ProgressOpts): string;
|
|
394
|
+
meter(opts?: MeterOpts): string;
|
|
355
395
|
dotspinner(opts?: DotspinnerOpts): string;
|
|
356
396
|
dotbar(opts?: DotbarOpts): string;
|
|
357
397
|
modal(opts?: ModalOpts): string;
|
|
@@ -360,6 +400,7 @@ export interface Ui {
|
|
|
360
400
|
prose(opts?: ProseOpts): string;
|
|
361
401
|
container(opts?: ContainerOpts): string;
|
|
362
402
|
tag(opts?: TagOpts): string;
|
|
403
|
+
inputIcon(opts?: InputIconOpts): string;
|
|
363
404
|
}
|
|
364
405
|
|
|
365
406
|
export declare const ui: Ui;
|
package/classes/index.js
CHANGED
|
@@ -68,6 +68,8 @@ export const cls = Object.freeze({
|
|
|
68
68
|
dotmatrixCell: 'ui-dotmatrix__cell',
|
|
69
69
|
dotmatrixCellHot: 'ui-dotmatrix__cell--hot',
|
|
70
70
|
dotmatrixCellAccent: 'ui-dotmatrix__cell--accent',
|
|
71
|
+
dotmatrixReveal: 'ui-dotmatrix--reveal',
|
|
72
|
+
dotmatrixPulse: 'ui-dotmatrix--pulse',
|
|
71
73
|
dotfield: 'ui-dotfield',
|
|
72
74
|
dotrule: 'ui-dotrule',
|
|
73
75
|
dotbar: 'ui-dotbar',
|
|
@@ -91,6 +93,9 @@ export const cls = Object.freeze({
|
|
|
91
93
|
hintError: 'ui-hint--error',
|
|
92
94
|
inputGroup: 'ui-input-group',
|
|
93
95
|
inputGroupAddon: 'ui-input-group__addon',
|
|
96
|
+
inputIcon: 'ui-input-icon',
|
|
97
|
+
inputIconSlot: 'ui-input-icon__icon',
|
|
98
|
+
inputIconEnd: 'ui-input-icon--end',
|
|
94
99
|
file: 'ui-file',
|
|
95
100
|
range: 'ui-range',
|
|
96
101
|
errorSummary: 'ui-error-summary',
|
|
@@ -122,6 +127,15 @@ export const cls = Object.freeze({
|
|
|
122
127
|
progress: 'ui-progress',
|
|
123
128
|
progressBar: 'ui-progress__bar',
|
|
124
129
|
progressIndeterminate: 'ui-progress--indeterminate',
|
|
130
|
+
meter: 'ui-meter',
|
|
131
|
+
meterFill: 'ui-meter__fill',
|
|
132
|
+
meterAccent: 'ui-meter--accent',
|
|
133
|
+
meterSuccess: 'ui-meter--success',
|
|
134
|
+
meterWarning: 'ui-meter--warning',
|
|
135
|
+
meterDanger: 'ui-meter--danger',
|
|
136
|
+
steps: 'ui-steps',
|
|
137
|
+
stepsItem: 'ui-steps__item',
|
|
138
|
+
stepsItemDone: 'ui-steps__item--done',
|
|
125
139
|
// overlay
|
|
126
140
|
modal: 'ui-modal',
|
|
127
141
|
modalHead: 'ui-modal__head',
|
|
@@ -140,6 +154,8 @@ export const cls = Object.freeze({
|
|
|
140
154
|
comboboxList: 'ui-combobox__list',
|
|
141
155
|
comboboxOption: 'ui-combobox__option',
|
|
142
156
|
comboboxEmpty: 'ui-combobox__empty',
|
|
157
|
+
lightbox: 'ui-lightbox',
|
|
158
|
+
lightboxClose: 'ui-lightbox__close',
|
|
143
159
|
// disclosure
|
|
144
160
|
tabs: 'ui-tabs',
|
|
145
161
|
tabsList: 'ui-tabs__list',
|
|
@@ -159,6 +175,15 @@ export const cls = Object.freeze({
|
|
|
159
175
|
avatarSm: 'ui-avatar--sm',
|
|
160
176
|
avatarLg: 'ui-avatar--lg',
|
|
161
177
|
avatarGroup: 'ui-avatar-group',
|
|
178
|
+
carousel: 'ui-carousel',
|
|
179
|
+
carouselStage: 'ui-carousel__stage',
|
|
180
|
+
carouselViewport: 'ui-carousel__viewport',
|
|
181
|
+
carouselSlide: 'ui-carousel__slide',
|
|
182
|
+
carouselPrev: 'ui-carousel__prev',
|
|
183
|
+
carouselNext: 'ui-carousel__next',
|
|
184
|
+
carouselStatus: 'ui-carousel__status',
|
|
185
|
+
carouselThumbs: 'ui-carousel__thumbs',
|
|
186
|
+
carouselThumb: 'ui-carousel__thumb',
|
|
162
187
|
// table
|
|
163
188
|
table: 'ui-table',
|
|
164
189
|
tableDense: 'ui-table--dense',
|
|
@@ -203,6 +228,9 @@ export const cls = Object.freeze({
|
|
|
203
228
|
siteheaderSticky: 'ui-siteheader--sticky',
|
|
204
229
|
siteheaderBrand: 'ui-siteheader__brand',
|
|
205
230
|
siteheaderActions: 'ui-siteheader__actions',
|
|
231
|
+
pagehead: 'ui-pagehead',
|
|
232
|
+
pageheadTitle: 'ui-pagehead__title',
|
|
233
|
+
pageheadActions: 'ui-pagehead__actions',
|
|
206
234
|
sitenav: 'ui-sitenav',
|
|
207
235
|
sitemenu: 'ui-sitemenu',
|
|
208
236
|
sitemenuPanel: 'ui-sitemenu__panel',
|
|
@@ -213,6 +241,10 @@ export const cls = Object.freeze({
|
|
|
213
241
|
tagAccent: 'ui-tag--accent',
|
|
214
242
|
meta: 'ui-meta',
|
|
215
243
|
metaItem: 'ui-meta__item',
|
|
244
|
+
timeline: 'ui-timeline',
|
|
245
|
+
timelineItem: 'ui-timeline__item',
|
|
246
|
+
timelineTime: 'ui-timeline__time',
|
|
247
|
+
kbd: 'ui-kbd',
|
|
216
248
|
display: 'ui-display',
|
|
217
249
|
mono: 'ui-mono',
|
|
218
250
|
muted: 'ui-muted',
|
|
@@ -346,6 +378,14 @@ export const ui = {
|
|
|
346
378
|
tone === 'info' && cls.toastInfo,
|
|
347
379
|
),
|
|
348
380
|
progress: ({ indeterminate } = {}) => j(cls.progress, indeterminate && cls.progressIndeterminate),
|
|
381
|
+
meter: ({ tone } = {}) =>
|
|
382
|
+
j(
|
|
383
|
+
cls.meter,
|
|
384
|
+
tone === 'accent' && cls.meterAccent,
|
|
385
|
+
tone === 'success' && cls.meterSuccess,
|
|
386
|
+
tone === 'warning' && cls.meterWarning,
|
|
387
|
+
tone === 'danger' && cls.meterDanger,
|
|
388
|
+
),
|
|
349
389
|
dotspinner: ({ size } = {}) =>
|
|
350
390
|
j(cls.dotspinner, size === 'sm' && cls.dotspinnerSm, size === 'lg' && cls.dotspinnerLg),
|
|
351
391
|
dotbar: ({ indeterminate } = {}) => j(cls.dotbar, indeterminate && cls.dotbarIndeterminate),
|
|
@@ -357,6 +397,7 @@ export const ui = {
|
|
|
357
397
|
container: ({ narrow, wide } = {}) =>
|
|
358
398
|
j(cls.container, narrow && cls.containerNarrow, wide && cls.containerWide),
|
|
359
399
|
tag: ({ accent } = {}) => j(cls.tag, accent && cls.tagAccent),
|
|
400
|
+
inputIcon: ({ end } = {}) => j(cls.inputIcon, end && cls.inputIconEnd),
|
|
360
401
|
};
|
|
361
402
|
|
|
362
403
|
export default ui;
|