@threadlabs/looma 0.37.0 → 0.37.1
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/components/shared/icons.js +3 -0
- package/components/ui-button/ui-button.html +3 -12
- package/components/ui-card/ui-card.html +5 -5
- package/components/ui-checkbox/ui-checkbox.html +0 -6
- package/components/ui-color-picker/ui-color-picker.html +0 -9
- package/components/ui-combobox/ui-combobox.html +1 -13
- package/components/ui-cycle-button/ui-cycle-button.html +41 -0
- package/components/ui-cycle-button/ui-cycle-button.js +19 -0
- package/components/ui-dialog/ui-dialog.html +1 -1
- package/components/ui-icon/ui-icon.html +3 -0
- package/components/ui-icon-button/ui-icon-button.html +10 -14
- package/components/ui-input/ui-input.html +1 -16
- package/components/ui-input-group/ui-input-group.html +0 -10
- package/components/ui-menu/ui-menu.html +1 -1
- package/components/ui-popover/ui-popover.html +1 -1
- package/components/ui-radio/ui-radio.html +0 -6
- package/components/ui-select/ui-select.html +2 -8
- package/components/ui-switch/ui-switch.html +0 -6
- package/components/ui-tooltip/ui-tooltip.html +1 -1
- package/dist/index.js +47 -46
- package/docs/README.md +45 -6
- package/docs/card.html +2 -1
- package/docs/catalog.json +212 -37
- package/docs/customizer-render.mjs +7 -6
- package/docs/customizer.js +13 -19
- package/docs/theme.mjs +3 -3
- package/editor/icons.d.ts +3 -0
- package/editor/index.js +4 -1
- package/package.json +2 -2
- package/styles/ui-button.css +2 -14
- package/styles/ui-card.css +1 -1
- package/styles/ui-checkbox.css +0 -9
- package/styles/ui-color-picker.css +0 -13
- package/styles/ui-combobox.css +2 -28
- package/styles/ui-cycle-button.css +36 -0
- package/styles/ui-dialog.css +2 -2
- package/styles/ui-icon-button.css +6 -13
- package/styles/ui-input-group.css +0 -13
- package/styles/ui-input.css +2 -18
- package/styles/ui-menu.css +1 -1
- package/styles/ui-popover.css +1 -1
- package/styles/ui-radio.css +0 -9
- package/styles/ui-select.css +3 -10
- package/styles/ui-switch.css +0 -9
- package/styles/ui-tooltip.css +1 -1
- package/theme-system.css +14 -14
- package/tokens.css +2 -10
- package/vanilla/UiCycleButton.d.ts +29 -0
- package/vanilla/UiCycleButton.js +85 -0
- package/vanilla/UiIcon.js +1 -1
- package/vanilla/index.js +1 -0
- package/vue/UiButton.vue +2 -11
- package/vue/UiCard.vue +5 -3
- package/vue/UiCheckbox.vue +0 -6
- package/vue/UiColorPicker.vue +0 -9
- package/vue/UiCombobox.vue +2 -26
- package/vue/UiCycleButton.d.ts +69 -0
- package/vue/UiCycleButton.js +2 -0
- package/vue/UiCycleButton.vue +403 -0
- package/vue/UiDialog.vue +6 -2
- package/vue/UiIcon.vue +22 -0
- package/vue/UiIconButton.vue +2 -16
- package/vue/UiInput.vue +1 -22
- package/vue/UiInputGroup.vue +0 -10
- package/vue/UiMenu.vue +3 -1
- package/vue/UiPopover.vue +3 -1
- package/vue/UiRadio.vue +0 -6
- package/vue/UiSelect.vue +2 -8
- package/vue/UiSwitch.vue +0 -6
- package/vue/UiTooltip.vue +3 -1
- package/vue/chunks/UiAffordanceScope.js +1 -1
- package/vue/chunks/UiAvatar.js +1 -1
- package/vue/chunks/UiAvatarGroup.js +1 -1
- package/vue/chunks/UiBadge.js +1 -1
- package/vue/chunks/UiBreadcrumbItem.js +1 -1
- package/vue/chunks/UiBreadcrumbs.js +1 -1
- package/vue/chunks/UiButton.js +3 -3
- package/vue/chunks/UiCallout.js +1 -1
- package/vue/chunks/UiCard.js +4 -4
- package/vue/chunks/UiCheckbox.js +2 -2
- package/vue/chunks/UiCluster.js +1 -1
- package/vue/chunks/UiColorPicker.js +2 -2
- package/vue/chunks/UiCombobox.js +2 -2
- package/vue/chunks/UiContainer.js +1 -1
- package/vue/chunks/UiContextMenu.js +1 -1
- package/vue/chunks/UiCover.js +1 -1
- package/vue/chunks/UiCurveEditor.js +1 -1
- package/vue/chunks/UiCycleButton.js +352 -0
- package/vue/chunks/UiDescriptionItem.js +1 -1
- package/vue/chunks/UiDescriptionList.js +1 -1
- package/vue/chunks/UiDialog.js +2 -2
- package/vue/chunks/UiDisclosure.js +1 -1
- package/vue/chunks/UiEditable.js +1 -1
- package/vue/chunks/UiEditorBlockActions.js +1 -1
- package/vue/chunks/UiEditorChipEditor.js +1 -1
- package/vue/chunks/UiEditorCodeLanguage.js +1 -1
- package/vue/chunks/UiEditorFootnoteEditor.js +1 -1
- package/vue/chunks/UiEditorImageToolbar.js +1 -1
- package/vue/chunks/UiEditorInsertTableGrid.js +1 -1
- package/vue/chunks/UiEditorLinkCard.js +1 -1
- package/vue/chunks/UiEditorLinkForm.js +1 -1
- package/vue/chunks/UiEditorMentionMenu.js +1 -1
- package/vue/chunks/UiEditorMentionMenuItem.js +1 -1
- package/vue/chunks/UiEditorSlashMenu.js +1 -1
- package/vue/chunks/UiEditorSlashMenuGroup.js +1 -1
- package/vue/chunks/UiEditorSlashMenuItem.js +1 -1
- package/vue/chunks/UiEditorSurface.js +1 -1
- package/vue/chunks/UiEditorTableContextMenu.js +1 -1
- package/vue/chunks/UiEditorTableOverlay.js +1 -1
- package/vue/chunks/UiEditorTableToolbar.js +1 -1
- package/vue/chunks/UiEditorToolbar.js +1 -1
- package/vue/chunks/UiFloatingActionButton.js +1 -1
- package/vue/chunks/UiFormField.js +1 -1
- package/vue/chunks/UiGrid.js +1 -1
- package/vue/chunks/UiIcon.js +70 -2
- package/vue/chunks/UiIconButton.js +4 -4
- package/vue/chunks/UiImage.js +1 -1
- package/vue/chunks/UiInput.js +2 -2
- package/vue/chunks/UiInputGroup.js +2 -2
- package/vue/chunks/UiLightEditor.js +1 -1
- package/vue/chunks/UiList.js +1 -1
- package/vue/chunks/UiListItem.js +1 -1
- package/vue/chunks/UiListbox.js +1 -1
- package/vue/chunks/UiMenu.js +2 -2
- package/vue/chunks/UiMenuGroup.js +1 -1
- package/vue/chunks/UiMenuItem.js +1 -1
- package/vue/chunks/UiMeter.js +1 -1
- package/vue/chunks/UiNavItem.js +1 -1
- package/vue/chunks/UiNumberInput.js +1 -1
- package/vue/chunks/UiPageHeader.js +1 -1
- package/vue/chunks/UiPopover.js +2 -2
- package/vue/chunks/UiRadio.js +2 -2
- package/vue/chunks/UiRadioGroup.js +1 -1
- package/vue/chunks/UiReel.js +1 -1
- package/vue/chunks/UiScrollArea.js +1 -1
- package/vue/chunks/UiSearchResultRow.js +1 -1
- package/vue/chunks/UiSearchShell.js +1 -1
- package/vue/chunks/UiSection.js +1 -1
- package/vue/chunks/UiSelect.js +2 -2
- package/vue/chunks/UiSeparator.js +1 -1
- package/vue/chunks/UiSidebar.js +1 -1
- package/vue/chunks/UiSlider.js +1 -1
- package/vue/chunks/UiSpinner.js +1 -1
- package/vue/chunks/UiStack.js +1 -1
- package/vue/chunks/UiStatusMessage.js +1 -1
- package/vue/chunks/UiSwatch.js +1 -1
- package/vue/chunks/UiSwitch.js +2 -2
- package/vue/chunks/UiSwitcher.js +1 -1
- package/vue/chunks/UiTable.js +1 -1
- package/vue/chunks/UiTabs.js +1 -1
- package/vue/chunks/UiText.js +1 -1
- package/vue/chunks/UiTextarea.js +1 -1
- package/vue/chunks/UiToast.js +1 -1
- package/vue/chunks/UiToastRegion.js +1 -1
- package/vue/chunks/UiTooltip.js +2 -2
- package/vue/chunks/UiTree.js +1 -1
- package/vue/chunks/UiTreeItem.js +1 -1
- package/vue/chunks/props.js +12 -1
- package/vue/components.css +74 -179
- package/vue/editor/index.js +68 -0
- package/vue/index.d.ts +1 -0
- package/vue/index.js +2 -1
package/docs/customizer.js
CHANGED
|
@@ -22,8 +22,7 @@ export function connect(host) {
|
|
|
22
22
|
let alive = true;
|
|
23
23
|
let selectedExample = '';
|
|
24
24
|
let refinementTrigger;
|
|
25
|
-
let previewFrame = 0, pending = false,
|
|
26
|
-
const entryRecipe = structuredClone(recipe);
|
|
25
|
+
let previewFrame = 0, pending = false, candidate, gestureStart;
|
|
27
26
|
const abort = new AbortController();
|
|
28
27
|
const say = (text, error = false) => { message.textContent = text; message.setAttribute('role', error ? 'alert' : 'status'); };
|
|
29
28
|
const sayApplied = text => say(theme?.storageAvailable ? text : 'Theme applies to this page. Browser storage is unavailable; download CSS or a recipe to keep it.');
|
|
@@ -106,16 +105,15 @@ export function connect(host) {
|
|
|
106
105
|
changed = JSON.stringify(recipe) !== JSON.stringify(saved);
|
|
107
106
|
paint();
|
|
108
107
|
};
|
|
109
|
-
const
|
|
110
|
-
if (!
|
|
111
|
-
|
|
112
|
-
root.querySelector('[data-action="compare"]').setAttribute('aria-pressed', 'false');
|
|
108
|
+
const clearPreview = () => {
|
|
109
|
+
if (!candidate) return;
|
|
110
|
+
candidate = undefined; theme?.compare();
|
|
113
111
|
root.querySelector('[data-variation-confirm]').hidden = true;
|
|
114
112
|
};
|
|
115
113
|
const preview = next => {
|
|
116
114
|
const validated = validateRecipe(next);
|
|
117
115
|
if (JSON.stringify(validated.values) === JSON.stringify(recipe.values)) return;
|
|
118
|
-
|
|
116
|
+
clearPreview();
|
|
119
117
|
if (!pending) gestureStart = structuredClone(recipe);
|
|
120
118
|
recipe = validated; pending = true;
|
|
121
119
|
if (!previewFrame) previewFrame = view.requestAnimationFrame(() => {
|
|
@@ -189,17 +187,13 @@ export function connect(host) {
|
|
|
189
187
|
if (!button) { view.requestAnimationFrame(paint); return; }
|
|
190
188
|
if (button.dataset.action === 'save' && saving) return;
|
|
191
189
|
flush();
|
|
192
|
-
if (!['
|
|
190
|
+
if (!['preview-variation', 'apply-variation', 'cancel-variation'].includes(button.dataset.action)) clearPreview();
|
|
193
191
|
try {
|
|
194
192
|
switch (button.dataset.action) {
|
|
195
193
|
case 'undo': case 'redo':
|
|
196
194
|
theme?.[button.dataset.action](); show(theme?.recipe ?? recipe, false); sayApplied('Previous theme decision restored.'); break;
|
|
197
|
-
case 'compare':
|
|
198
|
-
candidate = undefined; comparing = !comparing; theme?.compare(comparing ? entryRecipe : undefined);
|
|
199
|
-
button.setAttribute('aria-pressed', String(comparing)); root.querySelector('[data-variation-confirm]').hidden = true;
|
|
200
|
-
say(comparing ? 'Comparing with the theme when you entered. Your edits remain intact. Choose Compare again to return.' : 'Back to your edited theme.'); break;
|
|
201
195
|
case 'preview-variation': {
|
|
202
|
-
|
|
196
|
+
clearPreview();
|
|
203
197
|
const locks = [...root.querySelectorAll('[data-family-lock]')].filter(control => control.querySelector('input')?.checked).map(control => control.dataset.familyLock);
|
|
204
198
|
candidate = nearbyVariation(recipe, root.querySelector('[data-variation-choice]').value, locks);
|
|
205
199
|
theme?.compare(candidate); root.querySelector('[data-variation-confirm]').hidden = false;
|
|
@@ -208,10 +202,10 @@ export function connect(host) {
|
|
|
208
202
|
break;
|
|
209
203
|
}
|
|
210
204
|
case 'apply-variation': {
|
|
211
|
-
const selected = candidate;
|
|
205
|
+
const selected = candidate; clearPreview();
|
|
212
206
|
if (selected) show(selected); sayApplied('Variation applied. Undo returns to your previous theme.'); break;
|
|
213
207
|
}
|
|
214
|
-
case 'cancel-variation':
|
|
208
|
+
case 'cancel-variation': clearPreview(); paint(); say('Variation cancelled; your theme is unchanged.'); break;
|
|
215
209
|
case 'light-top': case 'light-left': case 'light-center': {
|
|
216
210
|
const positions = { 'light-top': [.5, 0], 'light-left': [.15, .15], 'light-center': [.5, .5] };
|
|
217
211
|
const [x, y] = positions[button.dataset.action];
|
|
@@ -275,7 +269,7 @@ export function connect(host) {
|
|
|
275
269
|
if (event.target.matches('[data-light-editor]') || event.target.closest?.('[data-token]')) {
|
|
276
270
|
input(event); flush(); sayApplied('Theme remembered in this browser. Undo restores the previous decision.'); return;
|
|
277
271
|
}
|
|
278
|
-
flush();
|
|
272
|
+
flush(); clearPreview();
|
|
279
273
|
if (event.target.matches('[data-unit-for]')) {
|
|
280
274
|
const field = fields.get(event.target.dataset.unitFor);
|
|
281
275
|
try {
|
|
@@ -303,7 +297,7 @@ export function connect(host) {
|
|
|
303
297
|
const cancel = event => { if (event.target.matches('[data-light-editor], [data-editor-kind="curve"]')) { flush(false); say('Drag cancelled; the previous value is restored.'); } };
|
|
304
298
|
const keyboard = event => {
|
|
305
299
|
if (!(event.ctrlKey || event.metaKey) || event.key.toLowerCase() !== 'z' || event.target.closest?.('input,textarea,select,[contenteditable="true"]')) return;
|
|
306
|
-
event.preventDefault(); flush();
|
|
300
|
+
event.preventDefault(); flush(); clearPreview(); theme?.[event.shiftKey ? 'redo' : 'undo'](); show(theme?.recipe ?? recipe, false);
|
|
307
301
|
};
|
|
308
302
|
const ready = event => {
|
|
309
303
|
if (event.data?.type === 'looma-preview-ready' && [...root.querySelectorAll('iframe')].some(frame => frame.contentWindow === event.source)) paint();
|
|
@@ -312,7 +306,7 @@ export function connect(host) {
|
|
|
312
306
|
let fontRequest = 0;
|
|
313
307
|
const selectFont = async event => {
|
|
314
308
|
const control = event.target.closest?.('[data-font-picker]'); if (!control) return;
|
|
315
|
-
flush();
|
|
309
|
+
flush(); clearPreview();
|
|
316
310
|
const id = control.dataset.fontPicker, family = event.detail.value;
|
|
317
311
|
const fonts = { ...recipe.fonts };
|
|
318
312
|
if (family === 'system') delete fonts[id]; else fonts[id] = family;
|
|
@@ -358,5 +352,5 @@ export function connect(host) {
|
|
|
358
352
|
root.querySelector('[data-action="save"]').hidden = false;
|
|
359
353
|
}).catch(error => { if (alive && error.name !== 'AbortError') say(error.message, true); });
|
|
360
354
|
}
|
|
361
|
-
return () => { root.removeEventListener('toggle', updateSizes, true); flush();
|
|
355
|
+
return () => { root.removeEventListener('toggle', updateSizes, true); flush(); clearPreview(); root.removeEventListener('cancel', cancel); root.removeEventListener('keydown', keyboard); alive = false; abort.abort(); root.removeEventListener('looma-example-remove', remove); root.removeEventListener('input', input); root.removeEventListener('value-change', selectExample); root.removeEventListener('value-change', selectFont); root.removeEventListener('blur', blur, true); root.removeEventListener('change', change); root.removeEventListener('click', click); view.removeEventListener('beforeunload', flush); view.removeEventListener('message', ready); view.removeEventListener(themeEvent, synchronize); };
|
|
362
356
|
}
|
package/docs/theme.mjs
CHANGED
|
@@ -29,12 +29,12 @@ export const themeFields = [
|
|
|
29
29
|
['Size & spacing', 'line-weight', 'Line weight', '--ui-border-width', 'length', '1px', 'Shared edge weight; focus stays independently visible.'],
|
|
30
30
|
['Material', 'outer-depth', 'Outer depth', '--ui-outer-depth', 'nonnegative', '0.6', 'How strongly controls and floating surfaces rise above the page.'],
|
|
31
31
|
['Material', 'inner-depth', 'Inner depth', '--ui-inner-depth', 'nonnegative', '0.3', 'How strongly fields and pressed controls sit into their surface.'],
|
|
32
|
-
['Material', 'glassiness', 'Glassiness', '--ui-glassiness', 'fraction', '0', '
|
|
32
|
+
['Material', 'glassiness', 'Glassiness', '--ui-glassiness', 'fraction', '0', 'Clear through richly frosted: the upper range adds stronger blur, saturation and glass edges. Content stays readable.'],
|
|
33
33
|
['Material', 'surface-separation', 'Surface separation', '--ui-surface-separation', 'fraction', '0', 'One material offset, scaled by popup purpose and actual size: quiet tooltips through substantial dialogs.'],
|
|
34
34
|
['Material', 'translucency', 'Overlay translucency', '--ui-overlay-translucency', 'fraction', '0', 'How much background comes through floating surfaces.'],
|
|
35
35
|
['Material', 'edge-light', 'Edge light', '--ui-edge-light', 'fraction', '0', 'Light caught by surface edges, independent of depth.'],
|
|
36
36
|
['Material', 'finish', 'Finish', '--ui-finish', 'fraction', '0', 'Matte through polished: how strongly the material catches a reflection.'],
|
|
37
|
-
['Material', 'glow', 'Glow', '--ui-glow', 'fraction', '0', '
|
|
37
|
+
['Material', 'glow', 'Glow', '--ui-glow', 'fraction', '0', 'Reflected light beyond a surface, from a quiet halo to a vivid bloom at the upper end.'],
|
|
38
38
|
['Material', 'light-x', 'Light horizontal position', '--ui-light-x', 'fraction', '0.5', 'The light source from left to right, relative to each surface.'],
|
|
39
39
|
['Material', 'light-y', 'Light vertical position', '--ui-light-y', 'fraction', '0', 'The light source from top to bottom, relative to each surface.'],
|
|
40
40
|
['Material', 'light-spread', 'Light spread', '--ui-light-spread', 'fraction', '0.5', 'A concentrated spot through broad illumination.'],
|
|
@@ -187,7 +187,7 @@ const contrast = (a, b) => (Math.max(luminance(a), luminance(b)) + .05) / (Math.
|
|
|
187
187
|
// fill cannot wash out the label, even at maximum finish and light strength.
|
|
188
188
|
function reflection(fill, text) {
|
|
189
189
|
const labels = Array.isArray(text) ? text : [text];
|
|
190
|
-
let amount = .
|
|
190
|
+
let amount = .6;
|
|
191
191
|
while (amount > 0 && labels.some(label => contrast(mix('#ffffff', fill, amount), label) < 4.5)) amount = Math.max(0, amount - .005);
|
|
192
192
|
return mix('#ffffff', fill, amount);
|
|
193
193
|
}
|
package/editor/icons.d.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { type IconNode } from 'lucide';
|
|
2
2
|
/** The opinionated Lucide set used by Looma's shipped interaction surfaces. */
|
|
3
3
|
export declare const LOOMA_ICONS: {
|
|
4
|
+
monitor: IconNode;
|
|
5
|
+
sun: IconNode;
|
|
6
|
+
moon: IconNode;
|
|
4
7
|
'align-center': IconNode;
|
|
5
8
|
'align-left': IconNode;
|
|
6
9
|
'align-right': IconNode;
|
package/editor/index.js
CHANGED
|
@@ -2,10 +2,13 @@ import { n as TABLE_CELL_BACKGROUND_PRESETS, t as TABLE_CELL_BACKGROUND_OPTIONS
|
|
|
2
2
|
import { n as resolveTableCellAt, t as measureTableOverlayGeometry } from "./chunks/ui.js";
|
|
3
3
|
import { $ as LOOMA_ACTIVE_BLOCK_BLUR_GRACE_MS, A as filterLoomaMentionItems, B as LOOMA_FOOTNOTE_LABEL, C as loomaMarkdownToHtml, D as createLoomaMentionExtension, E as LoomaMentionSuggestionPluginKey, F as LoomaTableOfContents, G as LoomaFigcaption, H as LoomaFootnoteReference, I as getTableOfContentsEntries, J as revealLoomaExpandAt, K as LoomaFigure, L as normalizeTableOfContentsConfig, M as LoomaImage, N as normalizeImageDimension, O as DEFAULT_MENTION_RESULT_LIMIT, P as normalizeImagePlacement, Q as LoomaCallout, R as LoomaTab, S as loomaMarkdownFromDoc, T as siteRelativeHref, U as LoomaFootnotes, V as LoomaFootnote, W as findLoomaFootnote, X as LoomaChip, Y as LOOMA_CHIP_COLORS, Z as normalizeLoomaChipColor, _ as getActiveTableCellAlignment, a as getActiveTableUiState, b as setActiveTableCellBackground, c as insertTableAtRange, d as LoomaTableKit, et as LOOMA_ACTIVE_BLOCK_CLASS, f as getDefaultEditorExtensions, g as LoomaTableHeader, h as LoomaTableCell, i as getDefaultSlashCommands, j as normalizeMentionResultLimit, k as MAX_MENTION_RESULT_LIMIT, l as normalizeActiveTableColumnWidths, m as LoomaTable, n as createLoomaSlashCommandExtension, nt as LoomaActiveBlock, o as handleTableAction, p as getLoomaTableExtensions, q as LoomaExpand, r as filterLoomaSlashCommands, rt as LoomaActiveBlockPluginKey, s as handleTableOverlayAction, t as LoomaSlashCommand, tt as LOOMA_ACTIVE_BLOCK_TYPING_IDLE_MS, u as shouldShowTextFormattingToolbar, v as getActiveTableCellBackground, w as createSiteRelativeLinks, x as LoomaSmartPaste, y as setActiveTableCellAlignment, z as LoomaTabs } from "./chunks/extensions.js";
|
|
4
4
|
import { a as setReferenceDisplay, i as referenceDisplay, n as LoomaReferencePresentation, o as LOOMA_CALLOUT_TONES, r as getReferenceDisplay, t as LoomaReference } from "./chunks/reference-display.js";
|
|
5
|
-
import { AlignCenter, AlignLeft, AlignRight, ArrowLeft, Bell, Bold, BookUser, Braces, Calculator, Check, ChevronDown, ChevronLeft, ChevronRight, CircleCheck, CircleDot, CircleQuestionMark, CircleX, CodeXml, Columns3, Compass, CreditCard, Ellipsis, Eraser, ExternalLink, FileText, Folder, GripHorizontal, GripVertical, Heading1, Heading2, Heading3, Highlighter, History, Image, Info, Italic, LayoutDashboard, Lightbulb, Link, List, ListOrdered, ListTodo, LoaderCircle, Merge, MessageSquareWarning, Minus, NotebookPen, PaintBucket, PanelBottom, PanelLeft, PanelRight, PanelTop, Paperclip, Pencil, Pilcrow, Plus, Quote, Receipt, Redo2, Rows3, Search, Settings, Split, Strikethrough, Superscript, Table2, Tag, Trash2, TriangleAlert, Truck, Underline, Undo2, Unlink, UserRound, Users, X } from "lucide";
|
|
5
|
+
import { AlignCenter, AlignLeft, AlignRight, ArrowLeft, Bell, Bold, BookUser, Braces, Calculator, Check, ChevronDown, ChevronLeft, ChevronRight, CircleCheck, CircleDot, CircleQuestionMark, CircleX, CodeXml, Columns3, Compass, CreditCard, Ellipsis, Eraser, ExternalLink, FileText, Folder, GripHorizontal, GripVertical, Heading1, Heading2, Heading3, Highlighter, History, Image, Info, Italic, LayoutDashboard, Lightbulb, Link, List, ListOrdered, ListTodo, LoaderCircle, Merge, MessageSquareWarning, Minus, Monitor, Moon, NotebookPen, PaintBucket, PanelBottom, PanelLeft, PanelRight, PanelTop, Paperclip, Pencil, Pilcrow, Plus, Quote, Receipt, Redo2, Rows3, Search, Settings, Split, Strikethrough, Sun, Superscript, Table2, Tag, Trash2, TriangleAlert, Truck, Underline, Undo2, Unlink, UserRound, Users, X } from "lucide";
|
|
6
6
|
//#region src/editor/icons.ts
|
|
7
7
|
/** The opinionated Lucide set used by Looma's shipped interaction surfaces. */
|
|
8
8
|
var LOOMA_ICONS = {
|
|
9
|
+
monitor: Monitor,
|
|
10
|
+
sun: Sun,
|
|
11
|
+
moon: Moon,
|
|
9
12
|
"align-center": AlignCenter,
|
|
10
13
|
"align-left": AlignLeft,
|
|
11
14
|
"align-right": AlignRight,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@threadlabs/looma",
|
|
3
|
-
"version": "0.37.
|
|
3
|
+
"version": "0.37.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Looma components as HTML, Vue, and plain DOM, with design tokens.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -127,7 +127,7 @@
|
|
|
127
127
|
"@tiptap/pm": ">=2 <3",
|
|
128
128
|
"@tiptap/vue-3": ">=2 <3",
|
|
129
129
|
"vue": "^3.5.43",
|
|
130
|
-
"markupress": "^0.8.7",
|
|
130
|
+
"markupress": "^0.8.7 || ^0.9.0",
|
|
131
131
|
"@nextwebwg/htmlkit": "1.0.0-alpha.69",
|
|
132
132
|
"vite": "^8.3.4"
|
|
133
133
|
},
|
package/styles/ui-button.css
CHANGED
|
@@ -451,18 +451,9 @@
|
|
|
451
451
|
}
|
|
452
452
|
|
|
453
453
|
/* The size states outrank :host, so sm is named too, or a small button would stay small. */
|
|
454
|
-
@media (pointer: coarse) {
|
|
455
|
-
:scope:where([data-component~="ui-button"]) {
|
|
456
|
-
min-block-size: max(var(--ui-control-size-md), var(--ui-control-min-block-size));
|
|
457
|
-
}
|
|
458
|
-
:scope:where([data-component~="ui-button"])[data-ui-button-state~="size=sm"] {
|
|
459
|
-
min-block-size: max(var(--ui-control-size-sm), var(--ui-control-min-block-size));
|
|
460
|
-
}
|
|
461
|
-
}
|
|
462
454
|
|
|
463
455
|
/* Under touch, a link-style button's press lands within the control minimum: an invisible hit
|
|
464
|
-
area, centred on it, like IconButton's. A
|
|
465
|
-
a link-style one keeps its text size, so a standalone one ("See all" under a list) needs the
|
|
456
|
+
area, centred on it, like IconButton's. A link-style action keeps its text size, so a standalone one ("See all" under a list) needs the
|
|
466
457
|
area. xs sits inside a line of text the same way, so it keeps its size and gains the area too.
|
|
467
458
|
Only these need it: a hit area on every button would reach over its neighbours. */
|
|
468
459
|
html[data-ui-input-modality="touch"] :scope:where([data-component~="ui-button"])[data-appearance="link"],
|
|
@@ -567,12 +558,9 @@
|
|
|
567
558
|
/* Ghost keeps no border, but gains the same neutral surface as other disabled buttons. */
|
|
568
559
|
|
|
569
560
|
/* The size states outrank :host, so sm is named too, or a small button would stay small. */
|
|
570
|
-
@media (pointer: coarse) {
|
|
571
|
-
}
|
|
572
561
|
|
|
573
562
|
/* Under touch, a link-style button's press lands within the control minimum: an invisible hit
|
|
574
|
-
area, centred on it, like IconButton's. A
|
|
575
|
-
a link-style one keeps its text size, so a standalone one ("See all" under a list) needs the
|
|
563
|
+
area, centred on it, like IconButton's. A link-style action keeps its text size, so a standalone one ("See all" under a list) needs the
|
|
576
564
|
area. xs sits inside a line of text the same way, so it keeps its size and gains the area too.
|
|
577
565
|
Only these need it: a hit area on every button would reach over its neighbours. */
|
|
578
566
|
|
package/styles/ui-card.css
CHANGED
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
:scope:where([data-component~="ui-card"])[data-ui-card-state~="treatment=expressive"] {
|
|
55
|
-
--_ui-panel-glass: clamp(0, var(--ui-glassiness, 0), 1);
|
|
55
|
+
--_ui-panel-glass: calc(clamp(0, var(--ui-glassiness, 0), 1) + 2 * pow(clamp(0, var(--ui-glassiness, 0), 1), 4));
|
|
56
56
|
--_ui-panel-separation: clamp(0, var(--ui-surface-separation, 0), 1);
|
|
57
57
|
--_ui-panel-rim: calc((var(--_ui-panel-separation) + var(--_ui-panel-glass) * 0.25) * 0.65 * 8px);
|
|
58
58
|
border-width: calc(var(--ui-border-width) + var(--_ui-panel-rim));
|
package/styles/ui-checkbox.css
CHANGED
|
@@ -210,12 +210,6 @@
|
|
|
210
210
|
padding-block: max(0px, calc((var(--_row) - max(var(--_line), var(--_ui-checkbox-size, 1.125rem))) / 2)) !important;
|
|
211
211
|
}
|
|
212
212
|
|
|
213
|
-
@media (pointer: coarse) {
|
|
214
|
-
:scope:where([data-component~="ui-checkbox"])[data-ui-checkbox-state~="size=sm"] {
|
|
215
|
-
--_row: var(--ui-control-min-block-size);
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
|
|
219
213
|
/* A component that sets its display still honours the hidden attribute on its root. */
|
|
220
214
|
:scope:where([data-component~="ui-checkbox"])[hidden] {
|
|
221
215
|
display: none !important;
|
|
@@ -235,8 +229,5 @@
|
|
|
235
229
|
and the first line centres in that control height, so the label shares a row's baseline.
|
|
236
230
|
Multi-line labels and descriptions still grow downward from that first line. */
|
|
237
231
|
|
|
238
|
-
@media (pointer: coarse) {
|
|
239
|
-
}
|
|
240
|
-
|
|
241
232
|
/* A component that sets its display still honours the hidden attribute on its root. */
|
|
242
233
|
}
|
|
@@ -104,17 +104,4 @@
|
|
|
104
104
|
padding: 0 !important;
|
|
105
105
|
accent-color: var(--ui-accent-solid);
|
|
106
106
|
}
|
|
107
|
-
@media (pointer: coarse) {
|
|
108
|
-
:scope:where([data-component~="ui-color-picker"]) {
|
|
109
|
-
--_size: max(var(--ui-control-size-md), var(--ui-control-min-block-size));
|
|
110
|
-
}
|
|
111
|
-
:scope:where([data-component~="ui-color-picker"])[data-ui-color-picker-state~="size=sm"] {
|
|
112
|
-
--_size: max(var(--ui-control-size-sm), var(--ui-control-min-block-size));
|
|
113
|
-
--_font: var(--ui-font-size-md);
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
@scope ([data-component~="ui-color-picker"]) to ([data-component]) {
|
|
118
|
-
@media (pointer: coarse) {
|
|
119
|
-
}
|
|
120
107
|
}
|
package/styles/ui-combobox.css
CHANGED
|
@@ -310,20 +310,8 @@
|
|
|
310
310
|
white-space: nowrap;
|
|
311
311
|
}
|
|
312
312
|
@media (pointer: coarse) {
|
|
313
|
-
:scope:where([data-component~="ui-combobox"]) {
|
|
314
|
-
--_row: max(var(--ui-control-size-md), var(--ui-control-min-block-size));
|
|
315
|
-
}
|
|
316
|
-
button {
|
|
317
|
-
min-inline-size: 2.75rem;
|
|
318
|
-
min-block-size: calc(var(--_row) - 2 * var(--ui-border-width));
|
|
319
|
-
}
|
|
320
|
-
/* Under touch a small field is still a touch-sized target, as a small button is, and keeps
|
|
321
|
-
body-size text: below 16px, iOS zooms the page into the focused field. */
|
|
322
|
-
:scope:where([data-component~="ui-combobox"])[data-ui-combobox-state~="size=sm"] {
|
|
323
|
-
--_row: max(var(--ui-control-size-sm), var(--ui-control-min-block-size));
|
|
324
|
-
}
|
|
325
313
|
:scope:where([data-component~="ui-combobox"])[data-ui-combobox-state~="size=sm"] input {
|
|
326
|
-
font-size:
|
|
314
|
+
font-size: var(--ui-font-size-md);
|
|
327
315
|
}
|
|
328
316
|
}
|
|
329
317
|
@media (forced-colors: active) {
|
|
@@ -408,8 +396,6 @@
|
|
|
408
396
|
/* A ghost icon button: the affordance is the mark, not a box around it. */
|
|
409
397
|
/* A row with a tag or a description: the label and its tag on one line, the description under them. */
|
|
410
398
|
@media (pointer: coarse) {
|
|
411
|
-
/* Under touch a small field is still a touch-sized target, as a small button is, and keeps
|
|
412
|
-
body-size text: below 16px, iOS zooms the page into the focused field. */
|
|
413
399
|
}
|
|
414
400
|
@media (forced-colors: active) {
|
|
415
401
|
}
|
|
@@ -722,20 +708,8 @@
|
|
|
722
708
|
white-space: nowrap;
|
|
723
709
|
}
|
|
724
710
|
@media (pointer: coarse) {
|
|
725
|
-
:where([data-component~="ui-combobox"]):where(:scope, :not([data-component], [data-slotted]:not([data-slotted~="ui-combobox"]))) {
|
|
726
|
-
--_row: max(var(--ui-control-size-md), var(--ui-control-min-block-size));
|
|
727
|
-
}
|
|
728
|
-
button:where(:scope, :scope *) {
|
|
729
|
-
min-inline-size: 2.75rem;
|
|
730
|
-
min-block-size: calc(var(--_row) - 2 * var(--ui-border-width));
|
|
731
|
-
}
|
|
732
|
-
/* Under touch a small field is still a touch-sized target, as a small button is, and keeps
|
|
733
|
-
body-size text: below 16px, iOS zooms the page into the focused field. */
|
|
734
|
-
:where([data-component~="ui-combobox"])[data-ui-combobox-state~="size=sm"]:where(:scope, :not([data-component], [data-slotted]:not([data-slotted~="ui-combobox"]))) {
|
|
735
|
-
--_row: max(var(--ui-control-size-sm), var(--ui-control-min-block-size));
|
|
736
|
-
}
|
|
737
711
|
:where([data-component~="ui-combobox"])[data-ui-combobox-state~="size=sm"] input:where(:scope, :not([data-component], [data-slotted]:not([data-slotted~="ui-combobox"]))) {
|
|
738
|
-
font-size:
|
|
712
|
+
font-size: var(--ui-font-size-md);
|
|
739
713
|
}
|
|
740
714
|
}
|
|
741
715
|
@media (forced-colors: active) {
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/* Generated by HTML Next 1.0.0-alpha.69. Do not edit. */
|
|
2
|
+
@supports (-moz-appearance: none) {
|
|
3
|
+
:where([data-component], [data-slotted]) { --html-next-scope-owner: boundary; }
|
|
4
|
+
:where([data-slotted]:not([data-component])) { --html-next-scope-owner: projected !important; }
|
|
5
|
+
}
|
|
6
|
+
@supports (-moz-appearance: none) {
|
|
7
|
+
[data-component~="ui-cycle-button"] { --html-next-scope-owner: "ui-cycle-button" !important; }
|
|
8
|
+
}
|
|
9
|
+
@scope ([data-component~="ui-cycle-button"]) to ([data-component], [data-slotted]) {
|
|
10
|
+
:scope:where([data-component~="ui-cycle-button"]) {
|
|
11
|
+
display: inline-flex !important;
|
|
12
|
+
align-items: center !important;
|
|
13
|
+
justify-content: center !important;
|
|
14
|
+
gap: 0 !important;
|
|
15
|
+
margin: 0 !important;
|
|
16
|
+
padding: 0 !important;
|
|
17
|
+
vertical-align: middle;
|
|
18
|
+
}
|
|
19
|
+
:scope:where([data-component~="ui-cycle-button"])[hidden] {
|
|
20
|
+
display: none !important;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
@scope ([data-slotted~="ui-cycle-button"]:not([data-component])) to ([data-component], [data-slotted]) {
|
|
24
|
+
:where([data-component~="ui-cycle-button"]):where(:scope, :not([data-component], [data-slotted]:not([data-slotted~="ui-cycle-button"]))) {
|
|
25
|
+
display: inline-flex !important;
|
|
26
|
+
align-items: center !important;
|
|
27
|
+
justify-content: center !important;
|
|
28
|
+
gap: 0 !important;
|
|
29
|
+
margin: 0 !important;
|
|
30
|
+
padding: 0 !important;
|
|
31
|
+
vertical-align: middle;
|
|
32
|
+
}
|
|
33
|
+
:where([data-component~="ui-cycle-button"])[hidden]:where(:scope, :not([data-component], [data-slotted]:not([data-slotted~="ui-cycle-button"]))) {
|
|
34
|
+
display: none !important;
|
|
35
|
+
}
|
|
36
|
+
}
|
package/styles/ui-dialog.css
CHANGED
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
/* Purpose and measured size shape one shared separation lever. The content plane stays opaque;
|
|
75
75
|
transparency, saturation and edge light belong to the surrounding decorative material. */
|
|
76
76
|
:scope:where([data-component~="ui-dialog"]) {
|
|
77
|
-
--_ui-material-glassiness: clamp(0, var(--ui-glassiness, 0), 1);
|
|
77
|
+
--_ui-material-glassiness: calc(clamp(0, var(--ui-glassiness, 0), 1) + 2 * pow(clamp(0, var(--ui-glassiness, 0), 1), 4));
|
|
78
78
|
--_ui-material-separation: clamp(0, var(--ui-surface-separation, 0), 1);
|
|
79
79
|
--_ui-material-active: clamp(0, calc((var(--_ui-material-glassiness) + var(--_ui-material-separation)) * 100000), 1);
|
|
80
80
|
--_ui-material-rim: calc((var(--_ui-material-separation) + var(--_ui-material-glassiness) * 0.25) * var(--_ui-material-scale, 1) * 8px);
|
|
@@ -395,7 +395,7 @@
|
|
|
395
395
|
/* Purpose and measured size shape one shared separation lever. The content plane stays opaque;
|
|
396
396
|
transparency, saturation and edge light belong to the surrounding decorative material. */
|
|
397
397
|
:where([data-component~="ui-dialog"]):where(:scope, :not([data-component], [data-slotted]:not([data-slotted~="ui-dialog"]))) {
|
|
398
|
-
--_ui-material-glassiness: clamp(0, var(--ui-glassiness, 0), 1);
|
|
398
|
+
--_ui-material-glassiness: calc(clamp(0, var(--ui-glassiness, 0), 1) + 2 * pow(clamp(0, var(--ui-glassiness, 0), 1), 4));
|
|
399
399
|
--_ui-material-separation: clamp(0, var(--ui-surface-separation, 0), 1);
|
|
400
400
|
--_ui-material-active: clamp(0, calc((var(--_ui-material-glassiness) + var(--_ui-material-separation)) * 100000), 1);
|
|
401
401
|
--_ui-material-rim: calc((var(--_ui-material-separation) + var(--_ui-material-glassiness) * 0.25) * var(--_ui-material-scale, 1) * 8px);
|
|
@@ -331,14 +331,6 @@
|
|
|
331
331
|
--_size: var(--ui-control-size-lg);
|
|
332
332
|
}
|
|
333
333
|
|
|
334
|
-
@media (pointer: coarse) {
|
|
335
|
-
:scope:where([data-component~="ui-icon-button"])[data-ui-icon-button-state~="matchButton"] {
|
|
336
|
-
inline-size: max(var(--ui-icon-button-size, var(--_size)), var(--ui-control-min-block-size));
|
|
337
|
-
min-inline-size: max(var(--ui-icon-button-size, var(--_size)), var(--ui-control-min-block-size));
|
|
338
|
-
min-block-size: max(var(--ui-icon-button-size, var(--_size)), var(--ui-control-min-block-size));
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
|
|
342
334
|
:scope:where([data-component~="ui-icon-button"])[data-ui-icon-button-state~="round"] {
|
|
343
335
|
border-radius: var(--ui-radius-round);
|
|
344
336
|
}
|
|
@@ -348,14 +340,18 @@
|
|
|
348
340
|
background-color: var(--ui-icon-button-outline-surface, var(--_icon-button-outline-surface, var(--ui-surface-default)));
|
|
349
341
|
background-image: var(--ui-surface-highlight, none);
|
|
350
342
|
color: var(--ui-icon-button-outline-text, var(--_icon-button-text, var(--ui-text-primary)));
|
|
351
|
-
box-shadow:
|
|
343
|
+
box-shadow:
|
|
344
|
+
var(--ui-action-shadow, var(--_ui-action-shadow)),
|
|
345
|
+
var(--_tone-glow);
|
|
352
346
|
}
|
|
353
347
|
|
|
354
348
|
:scope:where([data-component~="ui-icon-button"])[data-appearance="solid"] {
|
|
355
349
|
background-color: var(--ui-icon-button-solid-surface, var(--_icon-button-solid-surface, var(--ui-accent-solid)));
|
|
356
350
|
background-image: var(--_tone-highlight);
|
|
357
351
|
color: var(--ui-icon-button-solid-text, var(--_icon-button-solid-text, var(--ui-text-on-accent)));
|
|
358
|
-
box-shadow:
|
|
352
|
+
box-shadow:
|
|
353
|
+
var(--ui-icon-button-solid-shadow, var(--ui-action-shadow, var(--_ui-action-shadow))),
|
|
354
|
+
var(--_tone-glow);
|
|
359
355
|
}
|
|
360
356
|
|
|
361
357
|
:scope:where([data-component~="ui-icon-button"]):hover:enabled:not([aria-disabled="true"]) {
|
|
@@ -509,9 +505,6 @@
|
|
|
509
505
|
|
|
510
506
|
/* A text button's companion uses control geometry; compact icon buttons keep their own density. */
|
|
511
507
|
|
|
512
|
-
@media (pointer: coarse) {
|
|
513
|
-
}
|
|
514
|
-
|
|
515
508
|
/* Native toggle state persists after pointer release, including during loading. */
|
|
516
509
|
|
|
517
510
|
@media (prefers-reduced-motion: reduce) {
|
|
@@ -89,16 +89,6 @@
|
|
|
89
89
|
min-block-size: var(--ui-control-size-lg);
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
-
@media (pointer: coarse) {
|
|
93
|
-
:scope:where([data-component~="ui-input-group"]) {
|
|
94
|
-
min-block-size: max(var(--ui-control-size-md), var(--ui-control-min-block-size));
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
:scope:where([data-component~="ui-input-group"]):has(.field [data-ui-input-state~="size=sm"]) {
|
|
98
|
-
min-block-size: var(--ui-control-min-block-size);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
92
|
:scope:where([data-component~="ui-input-group"]):hover:not(:has(:is(input, textarea):focus, :is(input, textarea):disabled, :is(input, textarea):read-only, [aria-invalid="true"], :is(:user-invalid, [data-user-invalid]))) {
|
|
103
93
|
border-color: var(--ui-control-border-hover, var(--ui-text-secondary));
|
|
104
94
|
}
|
|
@@ -249,9 +239,6 @@
|
|
|
249
239
|
|
|
250
240
|
/* The frame takes its input's size, so a small group lines up with small buttons and fields. */
|
|
251
241
|
|
|
252
|
-
@media (pointer: coarse) {
|
|
253
|
-
}
|
|
254
|
-
|
|
255
242
|
/* The ring shows when the field's input would show its own: when it is focus-visible, which a
|
|
256
243
|
text input is for a pointer as well as a keyboard. A focused action button draws its own. */
|
|
257
244
|
|
package/styles/ui-input.css
CHANGED
|
@@ -100,28 +100,13 @@
|
|
|
100
100
|
font-size: var(--ui-font-size-md);
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
-
/*
|
|
104
|
-
body-size text: below 16px, iOS zooms the page into the focused field. */
|
|
103
|
+
/* Touch may use body-size text in a small native field to avoid focus zoom; this does not impose a larger visible control height. */
|
|
105
104
|
@media (pointer: coarse) {
|
|
106
|
-
:scope:where([data-component~="ui-input"]) {
|
|
107
|
-
min-block-size: var(
|
|
108
|
-
--ui-input-min-block-size,
|
|
109
|
-
var(--_ui-default-input-min-block-size, max(var(--ui-control-size-md), var(--ui-control-min-block-size)))
|
|
110
|
-
);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
105
|
:scope:where([data-component~="ui-input"]),
|
|
114
106
|
:scope:where([data-component~="ui-input"])[data-ui-input-state~="size=sm"],
|
|
115
107
|
:scope:where([data-component~="ui-input"])[data-ui-input-state~="size=lg"] {
|
|
116
108
|
font-size: var(--ui-font-size-md);
|
|
117
109
|
}
|
|
118
|
-
|
|
119
|
-
:scope:where([data-component~="ui-input"])[data-ui-input-state~="size=sm"] {
|
|
120
|
-
min-block-size: var(
|
|
121
|
-
--ui-input-min-block-size,
|
|
122
|
-
var(--_ui-default-input-min-block-size, max(var(--ui-control-size-sm), var(--ui-control-min-block-size)))
|
|
123
|
-
);
|
|
124
|
-
}
|
|
125
110
|
}
|
|
126
111
|
|
|
127
112
|
/* Tabbing into a field selects its text; tint that selection softly instead of the page highlight. */
|
|
@@ -195,8 +180,7 @@
|
|
|
195
180
|
|
|
196
181
|
/* Each size reads the hook and then an Input Group's default first, so a group, which draws the frame, can zero it. */
|
|
197
182
|
|
|
198
|
-
/*
|
|
199
|
-
body-size text: below 16px, iOS zooms the page into the focused field. */
|
|
183
|
+
/* Touch may use body-size text in a small native field to avoid focus zoom; this does not impose a larger visible control height. */
|
|
200
184
|
@media (pointer: coarse) {
|
|
201
185
|
}
|
|
202
186
|
|
package/styles/ui-menu.css
CHANGED
|
@@ -103,7 +103,7 @@
|
|
|
103
103
|
/* Purpose and measured size shape one shared separation lever. The content plane stays opaque;
|
|
104
104
|
transparency, saturation and edge light belong to the surrounding decorative material. */
|
|
105
105
|
:scope:where([data-component~="ui-menu"]):not([inline]) .surface {
|
|
106
|
-
--_ui-material-glassiness: clamp(0, var(--ui-glassiness, 0), 1);
|
|
106
|
+
--_ui-material-glassiness: calc(clamp(0, var(--ui-glassiness, 0), 1) + 2 * pow(clamp(0, var(--ui-glassiness, 0), 1), 4));
|
|
107
107
|
--_ui-material-separation: clamp(0, var(--ui-surface-separation, 0), 1);
|
|
108
108
|
--_ui-material-active: clamp(0, calc((var(--_ui-material-glassiness) + var(--_ui-material-separation)) * 100000), 1);
|
|
109
109
|
--_ui-material-rim: calc((var(--_ui-material-separation) + var(--_ui-material-glassiness) * 0.25) * var(--_ui-material-scale, 0.28) * 8px);
|
package/styles/ui-popover.css
CHANGED
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
/* Purpose and measured size shape one shared separation lever. The content plane stays opaque;
|
|
75
75
|
transparency, saturation and edge light belong to the surrounding decorative material. */
|
|
76
76
|
.surface {
|
|
77
|
-
--_ui-material-glassiness: clamp(0, var(--ui-glassiness, 0), 1);
|
|
77
|
+
--_ui-material-glassiness: calc(clamp(0, var(--ui-glassiness, 0), 1) + 2 * pow(clamp(0, var(--ui-glassiness, 0), 1), 4));
|
|
78
78
|
--_ui-material-separation: clamp(0, var(--ui-surface-separation, 0), 1);
|
|
79
79
|
--_ui-material-active: clamp(0, calc((var(--_ui-material-glassiness) + var(--_ui-material-separation)) * 100000), 1);
|
|
80
80
|
--_ui-material-rim: calc((var(--_ui-material-separation) + var(--_ui-material-glassiness) * 0.25) * var(--_ui-material-scale, 0.55) * 8px);
|
package/styles/ui-radio.css
CHANGED
|
@@ -110,12 +110,6 @@
|
|
|
110
110
|
padding-block: max(0px, calc((var(--_row) - max(var(--_line), var(--_ui-radio-size, 1.125rem))) / 2)) !important;
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
-
@media (pointer: coarse) {
|
|
114
|
-
:scope:where([data-component~="ui-radio"])[data-ui-radio-state~="size=sm"] {
|
|
115
|
-
--_row: var(--ui-control-min-block-size);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
113
|
/* A component that sets its display still honours the hidden attribute on its root. */
|
|
120
114
|
:scope:where([data-component~="ui-radio"])[hidden] {
|
|
121
115
|
display: none !important;
|
|
@@ -130,8 +124,5 @@
|
|
|
130
124
|
and the first line centres in that control height, so the label shares a row's baseline.
|
|
131
125
|
Multi-line labels and descriptions still grow downward from that first line. */
|
|
132
126
|
|
|
133
|
-
@media (pointer: coarse) {
|
|
134
|
-
}
|
|
135
|
-
|
|
136
127
|
/* A component that sets its display still honours the hidden attribute on its root. */
|
|
137
128
|
}
|
package/styles/ui-select.css
CHANGED
|
@@ -143,16 +143,10 @@
|
|
|
143
143
|
font-size: var(--ui-font-size-md);
|
|
144
144
|
}
|
|
145
145
|
|
|
146
|
-
/*
|
|
147
|
-
body-size text: below 16px, iOS zooms the page into the focused field. */
|
|
146
|
+
/* Touch may use body-size text in a small native field to avoid focus zoom; this does not impose a larger visible control height. */
|
|
148
147
|
@media (pointer: coarse) {
|
|
149
|
-
:scope:where([data-component~="ui-select"]) {
|
|
150
|
-
min-block-size: max(var(--ui-control-size-md), var(--ui-control-min-block-size));
|
|
151
|
-
}
|
|
152
|
-
|
|
153
148
|
:scope:where([data-component~="ui-select"])[data-ui-select-state~="size=sm"] {
|
|
154
|
-
|
|
155
|
-
font-size: inherit;
|
|
149
|
+
font-size: var(--ui-font-size-md);
|
|
156
150
|
}
|
|
157
151
|
}
|
|
158
152
|
|
|
@@ -169,8 +163,7 @@
|
|
|
169
163
|
|
|
170
164
|
/* The app's invalid flag, or the browser's own verdict once the user has left an invalid field. */
|
|
171
165
|
|
|
172
|
-
/*
|
|
173
|
-
body-size text: below 16px, iOS zooms the page into the focused field. */
|
|
166
|
+
/* Touch may use body-size text in a small native field to avoid focus zoom; this does not impose a larger visible control height. */
|
|
174
167
|
@media (pointer: coarse) {
|
|
175
168
|
}
|
|
176
169
|
|
package/styles/ui-switch.css
CHANGED
|
@@ -166,12 +166,6 @@
|
|
|
166
166
|
padding-block: max(0px, calc((var(--_row) - max(var(--_line), var(--_ui-switch-track-height, 1.5rem))) / 2)) !important;
|
|
167
167
|
}
|
|
168
168
|
|
|
169
|
-
@media (pointer: coarse) {
|
|
170
|
-
:scope:where([data-component~="ui-switch"])[data-ui-switch-state~="size=sm"] {
|
|
171
|
-
--_row: var(--ui-control-min-block-size);
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
|
|
175
169
|
/* A component that sets its display still honours the hidden attribute on its root. */
|
|
176
170
|
:scope:where([data-component~="ui-switch"])[hidden] {
|
|
177
171
|
display: none !important;
|
|
@@ -189,8 +183,5 @@
|
|
|
189
183
|
and the first line centres in that control height, so the label shares a row's baseline.
|
|
190
184
|
Multi-line labels and descriptions still grow downward from that first line. */
|
|
191
185
|
|
|
192
|
-
@media (pointer: coarse) {
|
|
193
|
-
}
|
|
194
|
-
|
|
195
186
|
/* A component that sets its display still honours the hidden attribute on its root. */
|
|
196
187
|
}
|
package/styles/ui-tooltip.css
CHANGED
|
@@ -106,7 +106,7 @@
|
|
|
106
106
|
/* Purpose and measured size shape one shared separation lever. The content plane stays opaque;
|
|
107
107
|
transparency, saturation and edge light belong to the surrounding decorative material. */
|
|
108
108
|
.surface {
|
|
109
|
-
--_ui-material-glassiness: clamp(0, var(--ui-glassiness, 0), 1);
|
|
109
|
+
--_ui-material-glassiness: calc(clamp(0, var(--ui-glassiness, 0), 1) + 2 * pow(clamp(0, var(--ui-glassiness, 0), 1), 4));
|
|
110
110
|
--_ui-material-separation: clamp(0, var(--ui-surface-separation, 0), 1);
|
|
111
111
|
--_ui-material-active: clamp(0, calc((var(--_ui-material-glassiness) + var(--_ui-material-separation)) * 100000), 1);
|
|
112
112
|
--_ui-material-rim: calc((var(--_ui-material-separation) + var(--_ui-material-glassiness) * 0.25) * var(--_ui-material-scale, 0.08) * 8px);
|