@threadlabs/looma 0.14.1 → 0.14.2
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/ui-meter/ui-meter.html +103 -0
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/styles/ui-meter.css +81 -0
- package/vanilla/UiMeter.d.ts +19 -0
- package/vanilla/UiMeter.js +28 -0
- package/vanilla/index.js +1 -0
- package/vue/UiMeter.d.ts +18 -0
- package/vue/UiMeter.js +2 -0
- package/vue/UiMeter.vue +194 -0
- package/vue/chunks/UiMeter.js +82 -0
- package/vue/components.css +60 -0
- package/vue/index.d.ts +1 -0
- package/vue/index.js +2 -1
package/package.json
CHANGED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/* Generated by HTML Next 1.0.0-alpha.7. Do not edit. */
|
|
2
|
+
@property --ui-meter-inline-size {
|
|
3
|
+
syntax: "*";
|
|
4
|
+
inherits: false;
|
|
5
|
+
}
|
|
6
|
+
@scope ([data-component~="ui-meter"]) to ([data-component], [data-slotted]) {
|
|
7
|
+
/* How far along something is: a track, filled from the start in the tone's colour. The track is a
|
|
8
|
+
quiet border colour, so an empty meter still shows; every tone's fill keeps 3:1 against the
|
|
9
|
+
track and the page. */
|
|
10
|
+
|
|
11
|
+
:scope {
|
|
12
|
+
--_meter-fill: var(--ui-text-muted);
|
|
13
|
+
|
|
14
|
+
display: inline-block;
|
|
15
|
+
flex: none;
|
|
16
|
+
vertical-align: middle;
|
|
17
|
+
inline-size: var(--ui-meter-inline-size, 8rem);
|
|
18
|
+
max-inline-size: 100%;
|
|
19
|
+
block-size: var(--ui-space-2);
|
|
20
|
+
overflow: hidden;
|
|
21
|
+
border-radius: var(--ui-radius-round);
|
|
22
|
+
background: var(--ui-border);
|
|
23
|
+
/* Unseen until forced colours draw it, where the track's own colour is gone. */
|
|
24
|
+
outline: 1px solid transparent;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
:scope[data-ui-meter-state~="size=sm"] {
|
|
28
|
+
inline-size: var(--ui-meter-inline-size, 5rem);
|
|
29
|
+
block-size: var(--ui-space-1);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.fill {
|
|
33
|
+
display: block;
|
|
34
|
+
block-size: 100%;
|
|
35
|
+
background: var(--_meter-fill);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
:scope[data-ui-meter-state~="tone=accent"] {
|
|
39
|
+
--_meter-fill: var(--ui-accent-solid);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
:scope[data-ui-meter-state~="tone=info"] {
|
|
43
|
+
--_meter-fill: var(--ui-info-solid);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
:scope[data-ui-meter-state~="tone=success"] {
|
|
47
|
+
--_meter-fill: var(--ui-success-solid);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
:scope[data-ui-meter-state~="tone=warning"] {
|
|
51
|
+
--_meter-fill: var(--ui-warning-solid);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
:scope[data-ui-meter-state~="tone=danger"] {
|
|
55
|
+
--_meter-fill: var(--ui-danger-solid);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/* Forced colours drop backgrounds: draw the fill in the text colour inside the outlined track. */
|
|
59
|
+
@media (forced-colors: active) {
|
|
60
|
+
.fill {
|
|
61
|
+
forced-color-adjust: none;
|
|
62
|
+
background: CanvasText;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/* A component that sets its display still honours the hidden attribute on its root. */
|
|
67
|
+
:scope[hidden] {
|
|
68
|
+
display: none;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
@scope ([data-component~="ui-meter"]) to ([data-component]) {
|
|
72
|
+
/* How far along something is: a track, filled from the start in the tone's colour. The track is a
|
|
73
|
+
quiet border colour, so an empty meter still shows; every tone's fill keeps 3:1 against the
|
|
74
|
+
track and the page. */
|
|
75
|
+
|
|
76
|
+
/* Forced colours drop backgrounds: draw the fill in the text colour inside the outlined track. */
|
|
77
|
+
@media (forced-colors: active) {
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/* A component that sets its display still honours the hidden attribute on its root. */
|
|
81
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// Generated by HTML Next 1.0.0-alpha.7 for Vanilla DOM. Do not edit.
|
|
2
|
+
export interface UiMeterEventMap {
|
|
3
|
+
}
|
|
4
|
+
export interface UiMeterElement extends HTMLSpanElement {
|
|
5
|
+
addEventListener<K extends keyof UiMeterEventMap>(type: K, listener: (this: UiMeterElement, event: UiMeterEventMap[K]) => unknown, options?: boolean | AddEventListenerOptions): void;
|
|
6
|
+
removeEventListener<K extends keyof UiMeterEventMap>(type: K, listener: (this: UiMeterElement, event: UiMeterEventMap[K]) => unknown, options?: boolean | EventListenerOptions): void;
|
|
7
|
+
}
|
|
8
|
+
export interface UiMeterProps {
|
|
9
|
+
label?: string | null;
|
|
10
|
+
max?: number | null;
|
|
11
|
+
size?: "sm" | "md" | null;
|
|
12
|
+
tone?: "neutral" | "accent" | "info" | "success" | "warning" | "danger" | null;
|
|
13
|
+
value?: number | null;
|
|
14
|
+
valueText?: string | null;
|
|
15
|
+
attributes?: Readonly<Record<string, string | number | boolean | null | undefined>>;
|
|
16
|
+
children?: readonly (string | Node)[];
|
|
17
|
+
slots?: Readonly<Record<string, readonly (string | Node)[]>>;
|
|
18
|
+
}
|
|
19
|
+
export declare function createUiMeter(props?: UiMeterProps): UiMeterElement;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// Generated by HTML Next 1.0.0-alpha.7 for Vanilla DOM. Do not edit.
|
|
2
|
+
import { manageComponentLifecycle } from "@nextwebwg/html-next/runtime";
|
|
3
|
+
import "../styles/ui-meter.css";
|
|
4
|
+
|
|
5
|
+
const definition = {...{"contract":{"tag":"ui-meter","props":{"label":{"type":"string","required":false,"target":{"attribute":"label"},"default":""},"max":{"type":"number","required":false,"target":{"attribute":"aria-valuemax"},"default":1},"size":{"type":{"enum":["sm","md"]},"required":false,"target":{"attribute":"size"},"default":"md"},"tone":{"type":{"enum":["neutral","accent","info","success","warning","danger"]},"required":false,"target":{"attribute":"tone"},"default":"neutral"},"value":{"type":"number","required":false,"target":{"attribute":"value"},"default":0},"valueText":{"type":"string","required":false,"target":{"attribute":"valuetext"},"default":""}}},"template":{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"role","value":"meter"},{"kind":"literal","name":"aria-valuemin","value":"0"},{"kind":"attribute","name":"aria-valuemax","expression":"max","expressionPlan":{"source":"max","ast":{"kind":"id","name":"max"},"dependencies":["max"]}},{"kind":"attribute","name":"aria-valuenow","expression":"amount","expressionPlan":{"source":"amount","ast":{"kind":"id","name":"amount"},"dependencies":["amount"]}},{"kind":"attribute","name":"aria-valuetext","expression":"{ true: valueText, false: format('%s%', whole) }[format('%s', valueText != '')]","expressionPlan":{"source":"{ true: valueText, false: format('%s%', whole) }[format('%s', valueText != '')]","ast":{"kind":"index","object":{"kind":"object","pairs":[{"key":"true","value":{"kind":"id","name":"valueText"}},{"key":"false","value":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s%"},{"kind":"id","name":"whole"}]}}]},"index":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s"},{"kind":"binary","op":"!=","left":{"kind":"id","name":"valueText"},"right":{"kind":"literal","value":""}}]}},"dependencies":["valueText","whole"]}},{"kind":"attribute","name":"aria-label","expression":"{ true: label, false: null }[format('%s', label != '')]","expressionPlan":{"source":"{ true: label, false: null }[format('%s', label != '')]","ast":{"kind":"index","object":{"kind":"object","pairs":[{"key":"true","value":{"kind":"id","name":"label"}},{"key":"false","value":{"kind":"literal","value":null}}]},"index":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s"},{"kind":"binary","op":"!=","left":{"kind":"id","name":"label"},"right":{"kind":"literal","value":""}}]}},"dependencies":["label"]}}],"children":[{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"fill"},{"kind":"attribute","name":"inline-size","expression":"format('%s%', percent)","expressionPlan":{"source":"format('%s%', percent)","ast":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s%"},{"kind":"id","name":"percent"}]},"dependencies":["percent"]},"target":"style"}],"children":[]}]},"declarations":[{"kind":"computed","name":"amount","expression":{"source":"clamp(0, value, max)","ast":{"kind":"call","fn":"clamp","args":[{"kind":"literal","value":0},{"kind":"id","name":"value"},{"kind":"id","name":"max"}]},"dependencies":["max","value"]}},{"kind":"computed","name":"percent","expression":{"source":"{ true: amount / max * 100, false: 0 }[format('%s', max > 0)]","ast":{"kind":"index","object":{"kind":"object","pairs":[{"key":"true","value":{"kind":"binary","op":"*","left":{"kind":"binary","op":"/","left":{"kind":"id","name":"amount"},"right":{"kind":"id","name":"max"}},"right":{"kind":"literal","value":100}}},{"key":"false","value":{"kind":"literal","value":0}}]},"index":{"kind":"call","fn":"format","args":[{"kind":"literal","value":"%s"},{"kind":"binary","op":">","left":{"kind":"id","name":"max"},"right":{"kind":"literal","value":0}}]}},"dependencies":["amount","max"]}},{"kind":"computed","name":"whole","expression":{"source":"percent + 0.5 - (percent + 0.5) % 1","ast":{"kind":"binary","op":"-","left":{"kind":"binary","op":"+","left":{"kind":"id","name":"percent"},"right":{"kind":"literal","value":0.5}},"right":{"kind":"binary","op":"%","left":{"kind":"binary","op":"+","left":{"kind":"id","name":"percent"},"right":{"kind":"literal","value":0.5}},"right":{"kind":"literal","value":1}}},"dependencies":["percent"]}}],"root":{"kind":"native","element":"span","choices":["span"]}},source:{file:import.meta.url},css:""};
|
|
6
|
+
|
|
7
|
+
export function createUiMeter(options = {}) {
|
|
8
|
+
const { attributes = {}, children = [], slots = {}, ...componentProps } = options;
|
|
9
|
+
const projected = [];
|
|
10
|
+
const element = document.createElement("span");
|
|
11
|
+
for (const [name, value] of Object.entries(attributes)) {
|
|
12
|
+
if (value === null || value === undefined || value === false) continue;
|
|
13
|
+
element.setAttribute(name, value === true ? "" : String(value));
|
|
14
|
+
}
|
|
15
|
+
if (!element.hasAttribute("role")) element.setAttribute("role", "meter");
|
|
16
|
+
if (!element.hasAttribute("aria-valuemin")) element.setAttribute("aria-valuemin", "0");
|
|
17
|
+
const value0 = componentProps["max"] === undefined ? 1 : componentProps["max"];
|
|
18
|
+
if (value0 === null || value0 === undefined) element.removeAttribute("aria-valuemax");
|
|
19
|
+
else element.setAttribute("aria-valuemax", String(value0));
|
|
20
|
+
element.setAttribute("data-component", "ui-meter");
|
|
21
|
+
const element0 = document.createElement("span");
|
|
22
|
+
element0.setAttribute("class", "fill");
|
|
23
|
+
element.append(element0);
|
|
24
|
+
manageComponentLifecycle(element, definition, { props: componentProps, projected,
|
|
25
|
+
});
|
|
26
|
+
return element;
|
|
27
|
+
}
|
|
28
|
+
|
package/vanilla/index.js
CHANGED
|
@@ -37,6 +37,7 @@ export * from "./UiList.js";
|
|
|
37
37
|
export * from "./UiListItem.js";
|
|
38
38
|
export * from "./UiMenu.js";
|
|
39
39
|
export * from "./UiMenuItem.js";
|
|
40
|
+
export * from "./UiMeter.js";
|
|
40
41
|
export * from "./UiNavItem.js";
|
|
41
42
|
export * from "./UiPageHeader.js";
|
|
42
43
|
export * from "./UiPopover.js";
|
package/vue/UiMeter.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
type __VLS_Props = {
|
|
2
|
+
label?: string;
|
|
3
|
+
max?: number;
|
|
4
|
+
size?: 'sm' | 'md';
|
|
5
|
+
tone?: 'neutral' | 'accent' | 'info' | 'success' | 'warning' | 'danger';
|
|
6
|
+
value?: number;
|
|
7
|
+
valueText?: string;
|
|
8
|
+
};
|
|
9
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
|
|
10
|
+
label: string;
|
|
11
|
+
size: "sm" | "md";
|
|
12
|
+
value: number;
|
|
13
|
+
max: number;
|
|
14
|
+
tone: "neutral" | "accent" | "info" | "success" | "warning" | "danger";
|
|
15
|
+
valueText: string;
|
|
16
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
17
|
+
declare const _default: typeof __VLS_export;
|
|
18
|
+
export default _default;
|
package/vue/UiMeter.js
ADDED
package/vue/UiMeter.vue
ADDED
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
<!-- Generated by HTML Next 1.0.0-alpha.7 for Vue 3.5. Do not edit. -->
|
|
2
|
+
<script setup lang="ts">
|
|
3
|
+
import { computed } from 'vue'
|
|
4
|
+
|
|
5
|
+
defineOptions({ inheritAttrs: false })
|
|
6
|
+
|
|
7
|
+
const props = withDefaults(
|
|
8
|
+
defineProps<{
|
|
9
|
+
label?: string
|
|
10
|
+
max?: number
|
|
11
|
+
size?: 'sm' | 'md'
|
|
12
|
+
tone?: 'neutral' | 'accent' | 'info' | 'success' | 'warning' | 'danger'
|
|
13
|
+
value?: number
|
|
14
|
+
valueText?: string
|
|
15
|
+
}>(),
|
|
16
|
+
{
|
|
17
|
+
label: '',
|
|
18
|
+
max: 1,
|
|
19
|
+
size: 'md',
|
|
20
|
+
tone: 'neutral',
|
|
21
|
+
value: 0,
|
|
22
|
+
valueText: '',
|
|
23
|
+
},
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
const amount = computed(() => Math.min(Math.max(0, props.value), props.max))
|
|
27
|
+
const percent = computed(() =>
|
|
28
|
+
({
|
|
29
|
+
true: number(
|
|
30
|
+
number(amount.value) === undefined || number(props.max) === undefined
|
|
31
|
+
? undefined
|
|
32
|
+
: number(amount.value)! / number(props.max)!,
|
|
33
|
+
) === undefined || number(100) === undefined
|
|
34
|
+
? undefined
|
|
35
|
+
: number(
|
|
36
|
+
number(amount.value) === undefined || number(props.max) === undefined
|
|
37
|
+
? undefined
|
|
38
|
+
: number(amount.value)! / number(props.max)!,
|
|
39
|
+
)! * number(100)!,
|
|
40
|
+
false: 0,
|
|
41
|
+
})[`${props.max > 0}`]
|
|
42
|
+
)
|
|
43
|
+
const whole = computed(
|
|
44
|
+
() => (number(
|
|
45
|
+
number(percent.value) === undefined || number(0.5) === undefined
|
|
46
|
+
? undefined
|
|
47
|
+
: number(percent.value)! + number(0.5)!,
|
|
48
|
+
) === undefined
|
|
49
|
+
|| number(
|
|
50
|
+
number(
|
|
51
|
+
number(percent.value) === undefined || number(0.5) === undefined
|
|
52
|
+
? undefined
|
|
53
|
+
: number(percent.value)! + number(0.5)!,
|
|
54
|
+
) === undefined || number(1) === undefined
|
|
55
|
+
? undefined
|
|
56
|
+
: number(
|
|
57
|
+
number(percent.value) === undefined || number(0.5) === undefined
|
|
58
|
+
? undefined
|
|
59
|
+
: number(percent.value)! + number(0.5)!,
|
|
60
|
+
)! % number(1)!,
|
|
61
|
+
) === undefined
|
|
62
|
+
? undefined
|
|
63
|
+
: number(
|
|
64
|
+
number(percent.value) === undefined || number(0.5) === undefined
|
|
65
|
+
? undefined
|
|
66
|
+
: number(percent.value)! + number(0.5)!,
|
|
67
|
+
)! - number(
|
|
68
|
+
number(
|
|
69
|
+
number(percent.value) === undefined || number(0.5) === undefined
|
|
70
|
+
? undefined
|
|
71
|
+
: number(percent.value)! + number(0.5)!,
|
|
72
|
+
) === undefined || number(1) === undefined
|
|
73
|
+
? undefined
|
|
74
|
+
: number(
|
|
75
|
+
number(percent.value) === undefined || number(0.5) === undefined
|
|
76
|
+
? undefined
|
|
77
|
+
: number(percent.value)! + number(0.5)!,
|
|
78
|
+
)! % number(1)!,
|
|
79
|
+
)!)
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
/** The values the styles' :host-state() rules test. */
|
|
83
|
+
const hostState = computed(() =>
|
|
84
|
+
[
|
|
85
|
+
props.size && `size size=${props.size}`,
|
|
86
|
+
props.tone && `tone tone=${props.tone}`,
|
|
87
|
+
].filter(Boolean).join(' ')
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
function text(value: unknown): string {
|
|
91
|
+
if (Array.isArray(value)) return value.map(text).join(' ')
|
|
92
|
+
return value === null || value === undefined || typeof value === 'object' ? '' : String(value)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function attribute(value: unknown): any {
|
|
96
|
+
if (
|
|
97
|
+
value === null || value === undefined || value === false
|
|
98
|
+
|| (typeof value === 'object' && !Array.isArray(value))
|
|
99
|
+
) return undefined
|
|
100
|
+
return value === true ? '' : text(value)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function number(value: unknown): number | undefined {
|
|
104
|
+
return typeof value === 'number' && !Number.isNaN(value) ? value : undefined
|
|
105
|
+
}
|
|
106
|
+
</script>
|
|
107
|
+
|
|
108
|
+
<template>
|
|
109
|
+
<span
|
|
110
|
+
data-component="ui-meter"
|
|
111
|
+
role="meter"
|
|
112
|
+
aria-valuemin="0"
|
|
113
|
+
v-bind="$attrs"
|
|
114
|
+
:aria-valuemax="max"
|
|
115
|
+
:aria-valuenow="amount"
|
|
116
|
+
:aria-valuetext="typeof (({ true: valueText, false: `${whole ?? ''}%` })[`${valueText !== ''}`]) === 'boolean'
|
|
117
|
+
? String(({ true: valueText, false: `${whole ?? ''}%` })[`${valueText !== ''}`])
|
|
118
|
+
: attribute(({ true: valueText, false: `${whole ?? ''}%` })[`${valueText !== ''}`])"
|
|
119
|
+
:aria-label="typeof (({ true: label, false: null })[`${label !== ''}`]) === 'boolean'
|
|
120
|
+
? String(({ true: label, false: null })[`${label !== ''}`])
|
|
121
|
+
: attribute(({ true: label, false: null })[`${label !== ''}`])"
|
|
122
|
+
:data-ui-meter-state="hostState || undefined"
|
|
123
|
+
><span class="fill" :style="{ 'inline-size': `${text(percent)}%` }"></span></span>
|
|
124
|
+
</template>
|
|
125
|
+
|
|
126
|
+
<style scoped>
|
|
127
|
+
/* How far along something is: a track, filled from the start in the tone's colour. The track is a
|
|
128
|
+
quiet border colour, so an empty meter still shows; every tone's fill keeps 3:1 against the
|
|
129
|
+
track and the page. */
|
|
130
|
+
@property --ui-meter-inline-size {
|
|
131
|
+
syntax: "*";
|
|
132
|
+
inherits: false;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
[data-component~="ui-meter"] {
|
|
136
|
+
--_meter-fill: var(--ui-text-muted);
|
|
137
|
+
|
|
138
|
+
display: inline-block;
|
|
139
|
+
flex: none;
|
|
140
|
+
vertical-align: middle;
|
|
141
|
+
inline-size: var(--ui-meter-inline-size, 8rem);
|
|
142
|
+
max-inline-size: 100%;
|
|
143
|
+
block-size: var(--ui-space-2);
|
|
144
|
+
overflow: hidden;
|
|
145
|
+
border-radius: var(--ui-radius-round);
|
|
146
|
+
background: var(--ui-border);
|
|
147
|
+
/* Unseen until forced colours draw it, where the track's own colour is gone. */
|
|
148
|
+
outline: 1px solid transparent;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
[data-component~="ui-meter"][data-ui-meter-state~="size=sm"] {
|
|
152
|
+
inline-size: var(--ui-meter-inline-size, 5rem);
|
|
153
|
+
block-size: var(--ui-space-1);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
.fill {
|
|
157
|
+
display: block;
|
|
158
|
+
block-size: 100%;
|
|
159
|
+
background: var(--_meter-fill);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
[data-component~="ui-meter"][data-ui-meter-state~="tone=accent"] {
|
|
163
|
+
--_meter-fill: var(--ui-accent-solid);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
[data-component~="ui-meter"][data-ui-meter-state~="tone=info"] {
|
|
167
|
+
--_meter-fill: var(--ui-info-solid);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
[data-component~="ui-meter"][data-ui-meter-state~="tone=success"] {
|
|
171
|
+
--_meter-fill: var(--ui-success-solid);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
[data-component~="ui-meter"][data-ui-meter-state~="tone=warning"] {
|
|
175
|
+
--_meter-fill: var(--ui-warning-solid);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
[data-component~="ui-meter"][data-ui-meter-state~="tone=danger"] {
|
|
179
|
+
--_meter-fill: var(--ui-danger-solid);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/* Forced colours drop backgrounds: draw the fill in the text colour inside the outlined track. */
|
|
183
|
+
@media (forced-colors: active) {
|
|
184
|
+
.fill {
|
|
185
|
+
forced-color-adjust: none;
|
|
186
|
+
background: CanvasText;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/* A component that sets its display still honours the hidden attribute on its root. */
|
|
191
|
+
[data-component~="ui-meter"][hidden] {
|
|
192
|
+
display: none;
|
|
193
|
+
}
|
|
194
|
+
</style>
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { t as _plugin_vue_export_helper_default } from "./_plugin-vue_export-helper.js";
|
|
2
|
+
import { computed, createElementBlock, createElementVNode, defineComponent, mergeProps, normalizeStyle, openBlock } from "vue";
|
|
3
|
+
//#region .build/vue/UiMeter.vue?vue&type=script&setup=true&lang.ts
|
|
4
|
+
var _hoisted_1 = [
|
|
5
|
+
"aria-valuemax",
|
|
6
|
+
"aria-valuenow",
|
|
7
|
+
"aria-valuetext",
|
|
8
|
+
"aria-label",
|
|
9
|
+
"data-ui-meter-state"
|
|
10
|
+
];
|
|
11
|
+
//#endregion
|
|
12
|
+
//#region .build/vue/UiMeter.vue
|
|
13
|
+
var UiMeter_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE__ */ defineComponent({
|
|
14
|
+
inheritAttrs: false,
|
|
15
|
+
__name: "UiMeter",
|
|
16
|
+
props: {
|
|
17
|
+
label: { default: "" },
|
|
18
|
+
max: { default: 1 },
|
|
19
|
+
size: { default: "md" },
|
|
20
|
+
tone: { default: "neutral" },
|
|
21
|
+
value: { default: 0 },
|
|
22
|
+
valueText: { default: "" }
|
|
23
|
+
},
|
|
24
|
+
setup(__props) {
|
|
25
|
+
const props = __props;
|
|
26
|
+
const amount = computed(() => Math.min(Math.max(0, props.value), props.max));
|
|
27
|
+
const percent = computed(() => ({
|
|
28
|
+
true: number(number(amount.value) === void 0 || number(props.max) === void 0 ? void 0 : number(amount.value) / number(props.max)) === void 0 || number(100) === void 0 ? void 0 : number(number(amount.value) === void 0 || number(props.max) === void 0 ? void 0 : number(amount.value) / number(props.max)) * number(100),
|
|
29
|
+
false: 0
|
|
30
|
+
})[`${props.max > 0}`]);
|
|
31
|
+
const whole = computed(() => number(number(percent.value) === void 0 || number(.5) === void 0 ? void 0 : number(percent.value) + number(.5)) === void 0 || number(number(number(percent.value) === void 0 || number(.5) === void 0 ? void 0 : number(percent.value) + number(.5)) === void 0 || number(1) === void 0 ? void 0 : number(number(percent.value) === void 0 || number(.5) === void 0 ? void 0 : number(percent.value) + number(.5)) % number(1)) === void 0 ? void 0 : number(number(percent.value) === void 0 || number(.5) === void 0 ? void 0 : number(percent.value) + number(.5)) - number(number(number(percent.value) === void 0 || number(.5) === void 0 ? void 0 : number(percent.value) + number(.5)) === void 0 || number(1) === void 0 ? void 0 : number(number(percent.value) === void 0 || number(.5) === void 0 ? void 0 : number(percent.value) + number(.5)) % number(1)));
|
|
32
|
+
/** The values the styles' :host-state() rules test. */
|
|
33
|
+
const hostState = computed(() => [props.size && `size size=${props.size}`, props.tone && `tone tone=${props.tone}`].filter(Boolean).join(" "));
|
|
34
|
+
function text(value) {
|
|
35
|
+
if (Array.isArray(value)) return value.map(text).join(" ");
|
|
36
|
+
return value === null || value === void 0 || typeof value === "object" ? "" : String(value);
|
|
37
|
+
}
|
|
38
|
+
function attribute(value) {
|
|
39
|
+
if (value === null || value === void 0 || value === false || typeof value === "object" && !Array.isArray(value)) return void 0;
|
|
40
|
+
return value === true ? "" : text(value);
|
|
41
|
+
}
|
|
42
|
+
function number(value) {
|
|
43
|
+
return typeof value === "number" && !Number.isNaN(value) ? value : void 0;
|
|
44
|
+
}
|
|
45
|
+
return (_ctx, _cache) => {
|
|
46
|
+
return openBlock(), createElementBlock("span", mergeProps({
|
|
47
|
+
"data-component": "ui-meter",
|
|
48
|
+
role: "meter",
|
|
49
|
+
"aria-valuemin": "0"
|
|
50
|
+
}, _ctx.$attrs, {
|
|
51
|
+
"aria-valuemax": __props.max,
|
|
52
|
+
"aria-valuenow": amount.value,
|
|
53
|
+
"aria-valuetext": typeof {
|
|
54
|
+
true: __props.valueText,
|
|
55
|
+
false: `${whole.value ?? ""}%`
|
|
56
|
+
}[`${__props.valueText !== ""}`] === "boolean" ? String({
|
|
57
|
+
true: __props.valueText,
|
|
58
|
+
false: `${whole.value ?? ""}%`
|
|
59
|
+
}[`${__props.valueText !== ""}`]) : attribute({
|
|
60
|
+
true: __props.valueText,
|
|
61
|
+
false: `${whole.value ?? ""}%`
|
|
62
|
+
}[`${__props.valueText !== ""}`]),
|
|
63
|
+
"aria-label": typeof {
|
|
64
|
+
true: __props.label,
|
|
65
|
+
false: null
|
|
66
|
+
}[`${__props.label !== ""}`] === "boolean" ? String({
|
|
67
|
+
true: __props.label,
|
|
68
|
+
false: null
|
|
69
|
+
}[`${__props.label !== ""}`]) : attribute({
|
|
70
|
+
true: __props.label,
|
|
71
|
+
false: null
|
|
72
|
+
}[`${__props.label !== ""}`]),
|
|
73
|
+
"data-ui-meter-state": hostState.value || void 0
|
|
74
|
+
}), [createElementVNode("span", {
|
|
75
|
+
class: "fill",
|
|
76
|
+
style: normalizeStyle({ "inline-size": `${text(percent.value)}%` })
|
|
77
|
+
}, null, 4)], 16, _hoisted_1);
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
}), [["__scopeId", "data-v-f716cd47"]]);
|
|
81
|
+
//#endregion
|
|
82
|
+
export { UiMeter_default as t };
|
package/vue/components.css
CHANGED
|
@@ -4436,6 +4436,66 @@ svg[data-v-006fa1b2-s] {
|
|
|
4436
4436
|
display: none;
|
|
4437
4437
|
}
|
|
4438
4438
|
|
|
4439
|
+
/* How far along something is: a track, filled from the start in the tone's colour. The track is a
|
|
4440
|
+
quiet border colour, so an empty meter still shows; every tone's fill keeps 3:1 against the
|
|
4441
|
+
track and the page. */
|
|
4442
|
+
@property --ui-meter-inline-size {
|
|
4443
|
+
syntax: "*";
|
|
4444
|
+
inherits: false;
|
|
4445
|
+
}
|
|
4446
|
+
[data-component~="ui-meter"][data-v-f716cd47] {
|
|
4447
|
+
--_meter-fill: var(--ui-text-muted);
|
|
4448
|
+
|
|
4449
|
+
display: inline-block;
|
|
4450
|
+
flex: none;
|
|
4451
|
+
vertical-align: middle;
|
|
4452
|
+
inline-size: var(--ui-meter-inline-size, 8rem);
|
|
4453
|
+
max-inline-size: 100%;
|
|
4454
|
+
block-size: var(--ui-space-2);
|
|
4455
|
+
overflow: hidden;
|
|
4456
|
+
border-radius: var(--ui-radius-round);
|
|
4457
|
+
background: var(--ui-border);
|
|
4458
|
+
/* Unseen until forced colours draw it, where the track's own colour is gone. */
|
|
4459
|
+
outline: 1px solid transparent;
|
|
4460
|
+
}
|
|
4461
|
+
[data-component~="ui-meter"][data-ui-meter-state~="size=sm"][data-v-f716cd47] {
|
|
4462
|
+
inline-size: var(--ui-meter-inline-size, 5rem);
|
|
4463
|
+
block-size: var(--ui-space-1);
|
|
4464
|
+
}
|
|
4465
|
+
.fill[data-v-f716cd47] {
|
|
4466
|
+
display: block;
|
|
4467
|
+
block-size: 100%;
|
|
4468
|
+
background: var(--_meter-fill);
|
|
4469
|
+
}
|
|
4470
|
+
[data-component~="ui-meter"][data-ui-meter-state~="tone=accent"][data-v-f716cd47] {
|
|
4471
|
+
--_meter-fill: var(--ui-accent-solid);
|
|
4472
|
+
}
|
|
4473
|
+
[data-component~="ui-meter"][data-ui-meter-state~="tone=info"][data-v-f716cd47] {
|
|
4474
|
+
--_meter-fill: var(--ui-info-solid);
|
|
4475
|
+
}
|
|
4476
|
+
[data-component~="ui-meter"][data-ui-meter-state~="tone=success"][data-v-f716cd47] {
|
|
4477
|
+
--_meter-fill: var(--ui-success-solid);
|
|
4478
|
+
}
|
|
4479
|
+
[data-component~="ui-meter"][data-ui-meter-state~="tone=warning"][data-v-f716cd47] {
|
|
4480
|
+
--_meter-fill: var(--ui-warning-solid);
|
|
4481
|
+
}
|
|
4482
|
+
[data-component~="ui-meter"][data-ui-meter-state~="tone=danger"][data-v-f716cd47] {
|
|
4483
|
+
--_meter-fill: var(--ui-danger-solid);
|
|
4484
|
+
}
|
|
4485
|
+
|
|
4486
|
+
/* Forced colours drop backgrounds: draw the fill in the text colour inside the outlined track. */
|
|
4487
|
+
@media (forced-colors: active) {
|
|
4488
|
+
.fill[data-v-f716cd47] {
|
|
4489
|
+
forced-color-adjust: none;
|
|
4490
|
+
background: CanvasText;
|
|
4491
|
+
}
|
|
4492
|
+
}
|
|
4493
|
+
|
|
4494
|
+
/* A component that sets its display still honours the hidden attribute on its root. */
|
|
4495
|
+
[data-component~="ui-meter"][hidden][data-v-f716cd47] {
|
|
4496
|
+
display: none;
|
|
4497
|
+
}
|
|
4498
|
+
|
|
4439
4499
|
/* This component's hooks style the element they are set on, and never a nested one. */
|
|
4440
4500
|
@property --ui-nav-item-current-surface {
|
|
4441
4501
|
syntax: "*";
|
package/vue/index.d.ts
CHANGED
|
@@ -37,6 +37,7 @@ export { default as List } from "./UiList.js";
|
|
|
37
37
|
export { default as ListItem } from "./UiListItem.js";
|
|
38
38
|
export { default as Menu } from "./UiMenu.js";
|
|
39
39
|
export { default as MenuItem } from "./UiMenuItem.js";
|
|
40
|
+
export { default as Meter } from "./UiMeter.js";
|
|
40
41
|
export { default as NavItem } from "./UiNavItem.js";
|
|
41
42
|
export { default as PageHeader } from "./UiPageHeader.js";
|
|
42
43
|
export { default as Popover } from "./UiPopover.js";
|
package/vue/index.js
CHANGED
|
@@ -38,6 +38,7 @@ import { t as UiList_default } from "./chunks/UiList.js";
|
|
|
38
38
|
import { t as UiListItem_default } from "./chunks/UiListItem.js";
|
|
39
39
|
import { t as UiMenu_default } from "./chunks/UiMenu.js";
|
|
40
40
|
import { t as UiMenuItem_default } from "./chunks/UiMenuItem.js";
|
|
41
|
+
import { t as UiMeter_default } from "./chunks/UiMeter.js";
|
|
41
42
|
import { t as UiNavItem_default } from "./chunks/UiNavItem.js";
|
|
42
43
|
import { t as UiPageHeader_default } from "./chunks/UiPageHeader.js";
|
|
43
44
|
import { t as UiPopover_default } from "./chunks/UiPopover.js";
|
|
@@ -65,4 +66,4 @@ import { t as UiTopBar_default } from "./chunks/UiTopBar.js";
|
|
|
65
66
|
import { t as UiTree_default } from "./chunks/UiTree.js";
|
|
66
67
|
import { t as UiTreeItem_default } from "./chunks/UiTreeItem.js";
|
|
67
68
|
import { trackInputModality } from "@threadlabs/looma/components/shared/input-modality.js";
|
|
68
|
-
export { UiActionBar_default as ActionBar, UiAffordanceScope_default as AffordanceScope, UiAvatar_default as Avatar, UiAvatarGroup_default as AvatarGroup, UiBadge_default as Badge, UiBreadcrumbItem_default as BreadcrumbItem, UiBreadcrumbs_default as Breadcrumbs, UiButton_default as Button, UiCallout_default as Callout, UiCard_default as Card, UiCheckbox_default as Checkbox, UiCluster_default as Cluster, UiCombobox_default as Combobox, UiContainer_default as Container, UiContextMenu_default as ContextMenu, UiCover_default as Cover, UiDescriptionItem_default as DescriptionItem, UiDescriptionList_default as DescriptionList, UiDialog_default as Dialog, UiDisclosure_default as Disclosure, UiEditable_default as Editable, UiEditorInsertTableGrid_default as EditorInsertTableGrid, UiEditorMentionMenu_default as EditorMentionMenu, UiEditorSlashMenu_default as EditorSlashMenu, UiEditorTableContextMenu_default as EditorTableContextMenu, UiEditorTableOverlay_default as EditorTableOverlay, UiEditorTableToolbar_default as EditorTableToolbar, UiEditorToolbar_default as EditorToolbar, UiFloatingActionButton_default as FloatingActionButton, UiFormField_default as FormField, UiGrid_default as Grid, UiIcon_default as Icon, UiIconButton_default as IconButton, UiInput_default as Input, UiInputGroup_default as InputGroup, UiList_default as List, UiListItem_default as ListItem, UiMenu_default as Menu, UiMenuItem_default as MenuItem, UiNavItem_default as NavItem, UiPageHeader_default as PageHeader, UiPopover_default as Popover, UiRadio_default as Radio, UiRadioGroup_default as RadioGroup, UiReel_default as Reel, UiScrollArea_default as ScrollArea, UiSearchResultRow_default as SearchResultRow, UiSearchShell_default as SearchShell, UiSection_default as Section, UiSelect_default as Select, UiSeparator_default as Separator, UiSidebar_default as Sidebar, UiSpinner_default as Spinner, UiStack_default as Stack, UiStatusMessage_default as StatusMessage, UiSwitch_default as Switch, UiSwitcher_default as Switcher, UiTable_default as Table, UiTabs_default as Tabs, UiText_default as Text, UiTextarea_default as Textarea, UiToastRegion_default as ToastRegion, UiTooltip_default as Tooltip, UiTopBar_default as TopBar, UiTree_default as Tree, UiTreeItem_default as TreeItem, trackInputModality };
|
|
69
|
+
export { UiActionBar_default as ActionBar, UiAffordanceScope_default as AffordanceScope, UiAvatar_default as Avatar, UiAvatarGroup_default as AvatarGroup, UiBadge_default as Badge, UiBreadcrumbItem_default as BreadcrumbItem, UiBreadcrumbs_default as Breadcrumbs, UiButton_default as Button, UiCallout_default as Callout, UiCard_default as Card, UiCheckbox_default as Checkbox, UiCluster_default as Cluster, UiCombobox_default as Combobox, UiContainer_default as Container, UiContextMenu_default as ContextMenu, UiCover_default as Cover, UiDescriptionItem_default as DescriptionItem, UiDescriptionList_default as DescriptionList, UiDialog_default as Dialog, UiDisclosure_default as Disclosure, UiEditable_default as Editable, UiEditorInsertTableGrid_default as EditorInsertTableGrid, UiEditorMentionMenu_default as EditorMentionMenu, UiEditorSlashMenu_default as EditorSlashMenu, UiEditorTableContextMenu_default as EditorTableContextMenu, UiEditorTableOverlay_default as EditorTableOverlay, UiEditorTableToolbar_default as EditorTableToolbar, UiEditorToolbar_default as EditorToolbar, UiFloatingActionButton_default as FloatingActionButton, UiFormField_default as FormField, UiGrid_default as Grid, UiIcon_default as Icon, UiIconButton_default as IconButton, UiInput_default as Input, UiInputGroup_default as InputGroup, UiList_default as List, UiListItem_default as ListItem, UiMenu_default as Menu, UiMenuItem_default as MenuItem, UiMeter_default as Meter, UiNavItem_default as NavItem, UiPageHeader_default as PageHeader, UiPopover_default as Popover, UiRadio_default as Radio, UiRadioGroup_default as RadioGroup, UiReel_default as Reel, UiScrollArea_default as ScrollArea, UiSearchResultRow_default as SearchResultRow, UiSearchShell_default as SearchShell, UiSection_default as Section, UiSelect_default as Select, UiSeparator_default as Separator, UiSidebar_default as Sidebar, UiSpinner_default as Spinner, UiStack_default as Stack, UiStatusMessage_default as StatusMessage, UiSwitch_default as Switch, UiSwitcher_default as Switcher, UiTable_default as Table, UiTabs_default as Tabs, UiText_default as Text, UiTextarea_default as Textarea, UiToastRegion_default as ToastRegion, UiTooltip_default as Tooltip, UiTopBar_default as TopBar, UiTree_default as Tree, UiTreeItem_default as TreeItem, trackInputModality };
|