@oods/components-vue 0.4.0 → 0.4.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/README.md +1 -1
- package/dist/index.cjs +337 -12
- package/dist/index.d.cts +168 -13
- package/dist/index.d.ts +168 -13
- package/dist/index.js +338 -15
- package/dist/ported.cjs +56 -6
- package/dist/ported.d.cts +10 -1
- package/dist/ported.d.ts +10 -1
- package/dist/ported.js +57 -7
- package/evidence/vue-readiness.v1.json +146 -0
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { defineComponent, h, useId, computed, ref, onMounted, watch, nextTick,
|
|
2
|
-
import { vizPreviewLayers, svgCarriesTitle, formatPriceAmount, formatPriceCode, formatReferenceLabel, summaryValue, formatDateTime, dateTimeInputValue, formatReadOnlyValue, BILLING_MINOR_UNITS, billingSummary, formatBillingAmount, billingAmountText, billingAmountMessage, parseBillingAmount, BILLING_INTERVALS, billingIntervalMessage, billingCycle, auditSummary, initialSort, ariaSort, nextSort, recipeItemLabels, DEFAULT_COLOR_STATES, geoFieldMapping, STATUS_ICON_SVG_ATTRS, STATUS_ICON_SHAPES, getStatusPresentation, resolveStatusIcon, currencyMinorUnits, billingPaymentSummary, billingPaymentRows, traitEventRows, vizControlFields, VIZ_CONTROL_TITLES, vizFieldValue, vizSummaryRows, editVizIntent } from '@oods/component-contracts';
|
|
1
|
+
import { defineComponent, h, useId, computed, ref, onMounted, onBeforeUnmount, watch, nextTick, isVNode, Text as Text$1, Comment, Fragment } from 'vue';
|
|
2
|
+
import { vizPreviewLayers, svgCarriesTitle, formatPriceAmount, formatPriceCode, formatReferenceLabel, ownershipPhrase, summaryValue, formatDateTime, dateTimeInputValue, formatReadOnlyValue, BILLING_MINOR_UNITS, billingSummary, formatBillingAmount, billingAmountText, billingAmountMessage, parseBillingAmount, BILLING_INTERVALS, billingIntervalMessage, billingCycle, auditSummary, initialSort, ariaSort, nextSort, recipeItemLabels, DEFAULT_COLOR_STATES, geoFieldMapping, STATUS_ICON_SVG_ATTRS, STATUS_ICON_SHAPES, getStatusPresentation, resolveStatusIcon, currencyMinorUnits, billingPaymentSummary, billingPaymentRows, traitEventRows, vizControlFields, VIZ_CONTROL_TITLES, vizFieldValue, vizSummaryRows, editVizIntent } from '@oods/component-contracts';
|
|
3
3
|
|
|
4
4
|
// src/primitives.ts
|
|
5
5
|
function statusIcon(name) {
|
|
@@ -185,6 +185,31 @@ var Button = defineComponent({
|
|
|
185
185
|
}
|
|
186
186
|
});
|
|
187
187
|
var canShowModal = () => typeof HTMLDialogElement !== "undefined" && typeof HTMLDialogElement.prototype.showModal === "function";
|
|
188
|
+
var pageLocks = 0;
|
|
189
|
+
var pageStyle;
|
|
190
|
+
function lockPageScroll() {
|
|
191
|
+
const page = document.documentElement;
|
|
192
|
+
if (pageLocks++ === 0) {
|
|
193
|
+
const scrollbar = window.innerWidth - page.clientWidth;
|
|
194
|
+
pageStyle = { overflow: page.style.overflow, paddingRight: page.style.paddingRight };
|
|
195
|
+
if (scrollbar > 0) page.style.paddingRight = `${parseFloat(getComputedStyle(page).paddingRight) + scrollbar}px`;
|
|
196
|
+
page.style.overflow = "hidden";
|
|
197
|
+
}
|
|
198
|
+
let held = true;
|
|
199
|
+
return () => {
|
|
200
|
+
if (!held) return;
|
|
201
|
+
held = false;
|
|
202
|
+
if (--pageLocks === 0 && pageStyle) {
|
|
203
|
+
page.style.overflow = pageStyle.overflow;
|
|
204
|
+
page.style.paddingRight = pageStyle.paddingRight;
|
|
205
|
+
pageStyle = void 0;
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
var outsideBox = (event, dialog) => {
|
|
210
|
+
const box = dialog.getBoundingClientRect();
|
|
211
|
+
return event.clientX < box.left || event.clientX > box.right || event.clientY < box.top || event.clientY > box.bottom;
|
|
212
|
+
};
|
|
188
213
|
var Dialog = defineComponent({
|
|
189
214
|
name: "OodsDialog",
|
|
190
215
|
props: {
|
|
@@ -206,15 +231,24 @@ var Dialog = defineComponent({
|
|
|
206
231
|
const element = ref(null);
|
|
207
232
|
const mounted = ref(false);
|
|
208
233
|
const managed = computed(() => props.modal && mounted.value && canShowModal());
|
|
234
|
+
let unlockScroll;
|
|
235
|
+
let pressedBackdrop = false;
|
|
236
|
+
const releaseScroll = () => {
|
|
237
|
+
unlockScroll?.();
|
|
238
|
+
unlockScroll = void 0;
|
|
239
|
+
};
|
|
209
240
|
const sync = () => {
|
|
210
241
|
const dialog = element.value;
|
|
211
242
|
if (!dialog || !managed.value) return;
|
|
212
|
-
if (props.open && !dialog.open)
|
|
213
|
-
|
|
243
|
+
if (props.open && !dialog.open) {
|
|
244
|
+
dialog.showModal();
|
|
245
|
+
unlockScroll ??= lockPageScroll();
|
|
246
|
+
} else if (!props.open && dialog.open) dialog.close();
|
|
214
247
|
};
|
|
215
248
|
onMounted(() => {
|
|
216
249
|
mounted.value = true;
|
|
217
250
|
});
|
|
251
|
+
onBeforeUnmount(releaseScroll);
|
|
218
252
|
watch([() => props.open, managed], sync, { flush: "post" });
|
|
219
253
|
const requestClose = (event) => {
|
|
220
254
|
event.preventDefault();
|
|
@@ -237,10 +271,23 @@ var Dialog = defineComponent({
|
|
|
237
271
|
if (event.key === "Escape" && !event.defaultPrevented) requestClose(event);
|
|
238
272
|
},
|
|
239
273
|
onCancel: requestClose,
|
|
240
|
-
//
|
|
241
|
-
//
|
|
274
|
+
// A close event from moving a mounted dialog into the top layer finds it open again, and is not reported. Any other
|
|
275
|
+
// close releases the page; when the browser closed it (a close request it would not let be cancelled) while open is
|
|
276
|
+
// still true, it is reported.
|
|
242
277
|
onClose: () => {
|
|
243
|
-
if (
|
|
278
|
+
if (element.value?.open) return;
|
|
279
|
+
releaseScroll();
|
|
280
|
+
if (props.open) emit("close");
|
|
281
|
+
},
|
|
282
|
+
onMousedown: (event) => {
|
|
283
|
+
pressedBackdrop = managed.value && event.target === event.currentTarget && outsideBox(event, event.currentTarget);
|
|
284
|
+
},
|
|
285
|
+
// s223-m02 (#2527 ruling 13b): a click on the backdrop emits close, as the close control does. A press that began
|
|
286
|
+
// inside the dialog (text selected and dragged out) is not a backdrop click.
|
|
287
|
+
onClick: (event) => {
|
|
288
|
+
const backdrop = pressedBackdrop && event.target === event.currentTarget && outsideBox(event, event.currentTarget);
|
|
289
|
+
pressedBackdrop = false;
|
|
290
|
+
if (backdrop) emit("close");
|
|
244
291
|
}
|
|
245
292
|
}, [
|
|
246
293
|
h("div", { class: "oods-dialog__header" }, [
|
|
@@ -803,12 +850,15 @@ function createBadgeFamily(options) {
|
|
|
803
850
|
};
|
|
804
851
|
for (const key of options.extraProps) props[key] = String;
|
|
805
852
|
for (const key of options.booleanProps ?? []) props[key] = { type: [String, Boolean], default: void 0 };
|
|
853
|
+
if (options.booleanProps) props.hideWhenFalse = { type: [Boolean, String], default: void 0 };
|
|
806
854
|
return defineComponent({
|
|
807
855
|
name: `Oods${options.component}`,
|
|
808
856
|
props,
|
|
809
857
|
setup(componentProps, { slots }) {
|
|
810
858
|
return () => {
|
|
811
859
|
const record = componentProps;
|
|
860
|
+
const flag = options.booleanProps?.map((key) => record[key]).find((value) => typeof value === "boolean");
|
|
861
|
+
if (record.hideWhenFalse === true && flag === false) return null;
|
|
812
862
|
const content = authoredContent(slots.default?.());
|
|
813
863
|
const scalar = scalarContent(content);
|
|
814
864
|
const read = (key) => typeof record[key] === "boolean" && options.booleanProps?.includes(key) ? String(record[key]) : record[key];
|
|
@@ -1435,12 +1485,13 @@ var TagSummary = defineComponent({
|
|
|
1435
1485
|
});
|
|
1436
1486
|
var OwnershipMeta = defineComponent({
|
|
1437
1487
|
name: "OodsOwnershipMeta",
|
|
1438
|
-
props: { title: String, label: String, heading: String, name: String, ownerType: String, owner_type: String, role: String, ownershipRole: String },
|
|
1488
|
+
props: { title: String, label: String, heading: String, name: String, ownerType: String, owner_type: String, role: String, ownershipRole: String, ownerLabel: String },
|
|
1439
1489
|
setup(props, { slots }) {
|
|
1440
1490
|
return () => {
|
|
1441
1491
|
const content = authoredContent(slots.default?.());
|
|
1442
1492
|
const terms = [["Owner Type", firstScalar(props.ownerType, props.owner_type)], ["Role", firstScalar(props.role, props.ownershipRole)]].filter((entry) => entry[1] !== void 0);
|
|
1443
|
-
|
|
1493
|
+
const phrase = props.ownerLabel !== void 0 ? ownershipPhrase(props.ownerLabel, firstScalar(props.ownerType, props.owner_type), firstScalar(props.role, props.ownershipRole)) : void 0;
|
|
1494
|
+
return h("div", { class: "oods-ownership-meta", "data-oods-component": "OwnershipMeta", "data-meta-type": "ownership" }, content.length ? content : phrase ? [h("span", { "data-meta-item": "true" }, phrase)] : [
|
|
1444
1495
|
h("span", { "data-meta-title": "true" }, firstText(props.title, props.label, props.heading, props.name) ?? "Ownership"),
|
|
1445
1496
|
...terms.map(([term, value]) => h("span", { key: term, "data-meta-item": "true" }, [h("strong", `${term}:`), ` ${value}`]))
|
|
1446
1497
|
]);
|
|
@@ -1470,11 +1521,14 @@ var CancellationBadge = createBadgeFamily({
|
|
|
1470
1521
|
booleanLabels: ["Cancellation scheduled", "No cancellation scheduled"]
|
|
1471
1522
|
});
|
|
1472
1523
|
var ArchiveSummary = defineComponent({
|
|
1524
|
+
// s224-m01 (#2542 ruling 6): hideWhenDefault is Boolean first, as the badges' hideWhenFalse is: a generated template writes
|
|
1525
|
+
// the bare attribute, which Vue casts to true only then.
|
|
1473
1526
|
name: "OodsArchiveSummary",
|
|
1474
|
-
props: { title: String, label: String, heading: String, name: String, isArchived: { type: [String, Boolean], default: void 0 }, archived: { type: [String, Boolean], default: void 0 }, status: { type: [String, Boolean], default: void 0 }, archivedAt: String, reason: String, archiveReason: String, summary: String, text: String, description: String },
|
|
1527
|
+
props: { title: String, label: String, heading: String, name: String, isArchived: { type: [String, Boolean], default: void 0 }, archived: { type: [String, Boolean], default: void 0 }, status: { type: [String, Boolean], default: void 0 }, archivedAt: String, reason: String, archiveReason: String, summary: String, text: String, description: String, hideWhenDefault: { type: [Boolean, String], default: void 0 } },
|
|
1475
1528
|
setup(props, { slots }) {
|
|
1476
1529
|
return () => {
|
|
1477
1530
|
const content = authoredContent(slots.default?.());
|
|
1531
|
+
if (props.hideWhenDefault === true && (props.isArchived ?? props.archived ?? props.status) === false && !props.archivedAt && !firstText(props.reason, props.archiveReason) && !content.length) return null;
|
|
1478
1532
|
const terms = [["Archived", summaryValue(props.isArchived ?? props.archived ?? props.status)], ["Archived At", props.archivedAt ? formatDateTime(props.archivedAt) : void 0], ["Reason", firstText(props.reason, props.archiveReason)]].filter((entry) => entry[1] !== void 0);
|
|
1479
1533
|
const fallback = firstText(props.summary, props.text, props.description);
|
|
1480
1534
|
return h("section", { class: "oods-archive-summary", "data-oods-component": "ArchiveSummary", "data-summary-type": "archive" }, [
|
|
@@ -2130,13 +2184,16 @@ var Tabs = defineComponent({
|
|
|
2130
2184
|
onClick: () => selectTab(item.id),
|
|
2131
2185
|
onKeydown: (event) => onTabKeydown(event, item.id)
|
|
2132
2186
|
}, slots.itemLabel?.({ item, selected: item.id === activeId.value }) ?? [item.label])),
|
|
2133
|
-
|
|
2187
|
+
// s224-m01 (#2542 ruling 2): the overflow markup is React's too: both class families, the trigger's data
|
|
2188
|
+
// attribute and aria-current="true" on an item.
|
|
2189
|
+
overflowItems.value.length > 0 ? h("div", { class: "oods-tabs-overflow oods-tabs__overflow" }, [
|
|
2134
2190
|
h("button", {
|
|
2135
2191
|
type: "button",
|
|
2136
2192
|
class: "oods-tabs-overflow-trigger",
|
|
2137
2193
|
"aria-label": `${props.overflowLabel} tabs`,
|
|
2138
2194
|
"aria-haspopup": "menu",
|
|
2139
2195
|
"aria-expanded": overflowOpen.value,
|
|
2196
|
+
"data-tabs-overflow-trigger": "true",
|
|
2140
2197
|
onClick: () => {
|
|
2141
2198
|
overflowOpen.value = !overflowOpen.value;
|
|
2142
2199
|
}
|
|
@@ -2146,7 +2203,7 @@ var Tabs = defineComponent({
|
|
|
2146
2203
|
type: "button",
|
|
2147
2204
|
role: "menuitem",
|
|
2148
2205
|
disabled: itemDisabled(item),
|
|
2149
|
-
"aria-current": item.id === activeId.value ? "
|
|
2206
|
+
"aria-current": item.id === activeId.value ? "true" : void 0,
|
|
2150
2207
|
onClick: () => {
|
|
2151
2208
|
selectTab(item.id);
|
|
2152
2209
|
overflowOpen.value = false;
|
|
@@ -2166,6 +2223,63 @@ var Tabs = defineComponent({
|
|
|
2166
2223
|
]);
|
|
2167
2224
|
}
|
|
2168
2225
|
});
|
|
2226
|
+
var SegmentedControl = defineComponent({
|
|
2227
|
+
name: "OodsSegmentedControl",
|
|
2228
|
+
props: {
|
|
2229
|
+
id: String,
|
|
2230
|
+
label: String,
|
|
2231
|
+
modelValue: String,
|
|
2232
|
+
value: String,
|
|
2233
|
+
defaultValue: { type: String, default: "" },
|
|
2234
|
+
name: String,
|
|
2235
|
+
size: { type: String, default: "md" },
|
|
2236
|
+
disabled: Boolean,
|
|
2237
|
+
options: { type: Array, default: () => [] }
|
|
2238
|
+
},
|
|
2239
|
+
emits: {
|
|
2240
|
+
"update:modelValue": (_value) => true,
|
|
2241
|
+
change: (_value) => true
|
|
2242
|
+
},
|
|
2243
|
+
setup(props, { emit, slots }) {
|
|
2244
|
+
const generatedId = useId();
|
|
2245
|
+
const internalValue = ref(props.defaultValue);
|
|
2246
|
+
const currentValue = computed(() => props.modelValue ?? props.value ?? internalValue.value);
|
|
2247
|
+
const select = (event) => {
|
|
2248
|
+
const next = event.target.value;
|
|
2249
|
+
if (props.modelValue === void 0 && props.value === void 0) internalValue.value = next;
|
|
2250
|
+
emit("update:modelValue", next);
|
|
2251
|
+
emit("change", next);
|
|
2252
|
+
};
|
|
2253
|
+
return () => {
|
|
2254
|
+
const id = props.id || `oods-segmentedcontrol-${generatedId}`;
|
|
2255
|
+
const label = slots.label?.() ?? props.label;
|
|
2256
|
+
return h("div", {
|
|
2257
|
+
class: "oods-field oods-segmented-control",
|
|
2258
|
+
"data-oods-component": "SegmentedControl",
|
|
2259
|
+
"data-size": props.size
|
|
2260
|
+
}, [
|
|
2261
|
+
h("span", { id: `${id}-label`, class: "oods-field-label" }, [label]),
|
|
2262
|
+
h("div", {
|
|
2263
|
+
id,
|
|
2264
|
+
role: "radiogroup",
|
|
2265
|
+
"aria-labelledby": `${id}-label`,
|
|
2266
|
+
class: "oods-segmented-control__track"
|
|
2267
|
+
}, props.options.map((option) => h("label", { key: option.value, class: "oods-segmented-control__option" }, [
|
|
2268
|
+
h("input", {
|
|
2269
|
+
type: "radio",
|
|
2270
|
+
class: "oods-segmented-control__input",
|
|
2271
|
+
name: props.name || id,
|
|
2272
|
+
value: option.value,
|
|
2273
|
+
checked: option.value === currentValue.value,
|
|
2274
|
+
disabled: props.disabled || option.disabled,
|
|
2275
|
+
onChange: select
|
|
2276
|
+
}),
|
|
2277
|
+
h("span", { class: "oods-segmented-control__label" }, option.label)
|
|
2278
|
+
])))
|
|
2279
|
+
]);
|
|
2280
|
+
};
|
|
2281
|
+
}
|
|
2282
|
+
});
|
|
2169
2283
|
function isRecord2(value) {
|
|
2170
2284
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2171
2285
|
}
|
|
@@ -2503,12 +2617,15 @@ var CancellationSummary = defineComponent({
|
|
|
2503
2617
|
cancelAtPeriodEndField: String,
|
|
2504
2618
|
requestedAtField: String,
|
|
2505
2619
|
reasonField: String,
|
|
2506
|
-
codeField: String
|
|
2620
|
+
codeField: String,
|
|
2621
|
+
// s224-m01 (#2542 ruling 6): Boolean first, as the badges' hideWhenFalse is (a bare attribute casts to true).
|
|
2622
|
+
hideWhenDefault: { type: [Boolean, String], default: void 0 }
|
|
2507
2623
|
},
|
|
2508
2624
|
setup(props, { attrs, slots }) {
|
|
2509
2625
|
return () => {
|
|
2510
2626
|
const slotValue = slotSummaryValue(slots);
|
|
2511
2627
|
const cancellationValue = props.cancelAtPeriodEnd ?? slotValue;
|
|
2628
|
+
if (props.hideWhenDefault === true && props.cancelAtPeriodEnd === false && !props.requestedAt && !props.reason && !props.code && slotValue === void 0) return null;
|
|
2512
2629
|
const rows = [];
|
|
2513
2630
|
if (cancellationValue !== void 0) {
|
|
2514
2631
|
rows.push(summaryEntry(
|
|
@@ -2983,7 +3100,8 @@ var array = Array;
|
|
|
2983
3100
|
function eventRecipe(id, kind, title) {
|
|
2984
3101
|
return defineComponent({ name: id, props: { id: String, title: { type: String, default: title }, archivedAt: String, restoredAt: String, archivedBy: String, reason: String, timestamp: String, code: String, history: array, status: String, showActor: { type: Boolean, default: true }, showReason: { type: Boolean, default: true } }, setup: (props) => () => {
|
|
2985
3102
|
const rows = traitEventRows(kind, props);
|
|
2986
|
-
|
|
3103
|
+
if (!rows.length) return null;
|
|
3104
|
+
return h("article", { id: props.id, class: "oods-trait-recipe", "data-oods-component": id, "aria-label": props.title }, [h("h2", props.title), h("ol", rows.map((row, index) => h("li", { key: index }, [h("strong", row.title), h("p", row.at ? h("time", { datetime: row.at }, row.time) : row.time), row.actor && h("p", `Actor: ${row.actor}`), row.reason && h("p", `Reason: ${row.reason}`), row.code && h("p", `Code: ${row.code}`)])))]);
|
|
2987
3105
|
} });
|
|
2988
3106
|
}
|
|
2989
3107
|
var ArchiveEvent = eventRecipe("ArchiveEvent", "archive", "Archive events");
|
|
@@ -3084,5 +3202,210 @@ var VizLinePreview = preview("VizLinePreview", "line");
|
|
|
3084
3202
|
var VizMarkPreview = preview("VizMarkPreview", "bar");
|
|
3085
3203
|
var VizPointPreview = preview("VizPointPreview", "scatter");
|
|
3086
3204
|
var VizScatterPreview = preview("VizScatterPreview", "scatter");
|
|
3205
|
+
var Combobox = defineComponent({
|
|
3206
|
+
name: "OodsCombobox",
|
|
3207
|
+
props: {
|
|
3208
|
+
id: String,
|
|
3209
|
+
label: String,
|
|
3210
|
+
options: { type: Array, default: () => [] },
|
|
3211
|
+
modelValue: String,
|
|
3212
|
+
value: String,
|
|
3213
|
+
defaultValue: { type: String, default: "" },
|
|
3214
|
+
placeholder: String,
|
|
3215
|
+
name: String,
|
|
3216
|
+
required: Boolean,
|
|
3217
|
+
disabled: Boolean,
|
|
3218
|
+
help: String,
|
|
3219
|
+
validation: Object,
|
|
3220
|
+
/** The control height, as Button, Input and Select: xs 24, sm 28, md 32 (default) or lg 40. */
|
|
3221
|
+
size: { type: String, default: "md" }
|
|
3222
|
+
},
|
|
3223
|
+
emits: {
|
|
3224
|
+
"update:modelValue": (_value) => true,
|
|
3225
|
+
change: (_value) => true
|
|
3226
|
+
},
|
|
3227
|
+
setup(props, { emit, slots }) {
|
|
3228
|
+
const generatedId = useId();
|
|
3229
|
+
const controlId = computed(() => props.id || `oods-combobox-${generatedId}`);
|
|
3230
|
+
const internalValue = ref(props.defaultValue);
|
|
3231
|
+
const query = ref(null);
|
|
3232
|
+
const open = ref(false);
|
|
3233
|
+
const active = ref(-1);
|
|
3234
|
+
const root = ref(null);
|
|
3235
|
+
const listbox = ref(null);
|
|
3236
|
+
const chosenValue = computed(() => props.modelValue ?? props.value ?? internalValue.value);
|
|
3237
|
+
const chosen = computed(() => props.options.find((option) => option.value === chosenValue.value));
|
|
3238
|
+
const text = computed(() => query.value ?? chosen.value?.label ?? "");
|
|
3239
|
+
const matches = computed(() => {
|
|
3240
|
+
const needle = (query.value ?? "").trim().toLowerCase();
|
|
3241
|
+
return props.options.map((option) => needle === "" || option.label.toLowerCase().includes(needle));
|
|
3242
|
+
});
|
|
3243
|
+
const reachable = computed(() => props.options.flatMap((option, index) => matches.value[index] && !option.disabled ? [index] : []));
|
|
3244
|
+
const optionId = (index) => `${controlId.value}-option-${index}`;
|
|
3245
|
+
const close = () => {
|
|
3246
|
+
open.value = false;
|
|
3247
|
+
active.value = -1;
|
|
3248
|
+
};
|
|
3249
|
+
const commit = (next) => {
|
|
3250
|
+
if (props.modelValue === void 0 && props.value === void 0) internalValue.value = next;
|
|
3251
|
+
emit("update:modelValue", next);
|
|
3252
|
+
emit("change", next);
|
|
3253
|
+
};
|
|
3254
|
+
const pick = (index) => {
|
|
3255
|
+
const option = props.options[index];
|
|
3256
|
+
if (!option || option.disabled) return;
|
|
3257
|
+
query.value = null;
|
|
3258
|
+
close();
|
|
3259
|
+
if (option.value !== chosenValue.value) commit(option.value);
|
|
3260
|
+
};
|
|
3261
|
+
const outside = (event) => {
|
|
3262
|
+
if (!root.value?.contains(event.target)) close();
|
|
3263
|
+
};
|
|
3264
|
+
watch(open, (isOpen) => {
|
|
3265
|
+
if (isOpen) document.addEventListener("pointerdown", outside);
|
|
3266
|
+
else document.removeEventListener("pointerdown", outside);
|
|
3267
|
+
});
|
|
3268
|
+
onBeforeUnmount(() => {
|
|
3269
|
+
if (typeof document !== "undefined") document.removeEventListener("pointerdown", outside);
|
|
3270
|
+
});
|
|
3271
|
+
watch([open, active], async () => {
|
|
3272
|
+
if (!open.value || active.value < 0) return;
|
|
3273
|
+
await nextTick();
|
|
3274
|
+
const element = listbox.value?.children[active.value];
|
|
3275
|
+
element?.scrollIntoView?.({ block: "nearest" });
|
|
3276
|
+
});
|
|
3277
|
+
const keydown = (event) => {
|
|
3278
|
+
if (event.defaultPrevented || props.disabled || event.isComposing) return;
|
|
3279
|
+
const order = reachable.value;
|
|
3280
|
+
const first = order[0] ?? -1;
|
|
3281
|
+
const last = order[order.length - 1] ?? -1;
|
|
3282
|
+
const at = order.indexOf(active.value);
|
|
3283
|
+
switch (event.key) {
|
|
3284
|
+
case "ArrowDown":
|
|
3285
|
+
event.preventDefault();
|
|
3286
|
+
active.value = !open.value || at === -1 ? first : order[(at + 1) % order.length];
|
|
3287
|
+
open.value = true;
|
|
3288
|
+
return;
|
|
3289
|
+
case "ArrowUp":
|
|
3290
|
+
event.preventDefault();
|
|
3291
|
+
active.value = !open.value || at <= 0 ? last : order[at - 1];
|
|
3292
|
+
open.value = true;
|
|
3293
|
+
return;
|
|
3294
|
+
case "Home":
|
|
3295
|
+
case "End":
|
|
3296
|
+
if (!open.value) return;
|
|
3297
|
+
event.preventDefault();
|
|
3298
|
+
active.value = event.key === "Home" ? first : last;
|
|
3299
|
+
return;
|
|
3300
|
+
case "Enter":
|
|
3301
|
+
if (!open.value) return;
|
|
3302
|
+
event.preventDefault();
|
|
3303
|
+
if (active.value >= 0) pick(active.value);
|
|
3304
|
+
return;
|
|
3305
|
+
case "Escape":
|
|
3306
|
+
if (open.value) {
|
|
3307
|
+
event.preventDefault();
|
|
3308
|
+
close();
|
|
3309
|
+
return;
|
|
3310
|
+
}
|
|
3311
|
+
if (text.value === "" && chosenValue.value === "") return;
|
|
3312
|
+
event.preventDefault();
|
|
3313
|
+
query.value = null;
|
|
3314
|
+
if (chosenValue.value !== "") commit("");
|
|
3315
|
+
return;
|
|
3316
|
+
case "Tab":
|
|
3317
|
+
if (open.value) close();
|
|
3318
|
+
return;
|
|
3319
|
+
}
|
|
3320
|
+
};
|
|
3321
|
+
return () => {
|
|
3322
|
+
const id = controlId.value;
|
|
3323
|
+
const label = slots.label?.() ?? props.label;
|
|
3324
|
+
const help = slots.help?.() ?? props.help;
|
|
3325
|
+
const validation = slots.validation?.() ?? props.validation?.message;
|
|
3326
|
+
const tone = props.validation ? props.validation.state === "error" ? "critical" : props.validation.state : void 0;
|
|
3327
|
+
const describedBy = [help ? `${id}-help` : void 0, validation ? `${id}-validation` : void 0].filter(Boolean).join(" ") || void 0;
|
|
3328
|
+
const noMatches = open.value && !matches.value.some(Boolean);
|
|
3329
|
+
return h("div", {
|
|
3330
|
+
ref: root,
|
|
3331
|
+
class: "oods-field oods-combobox",
|
|
3332
|
+
...tone ? { style: { "--cmp-input-message-border": `var(--sys-status-${tone}-border)`, "--cmp-input-message-text": `var(--sys-status-${tone}-text)` } } : {},
|
|
3333
|
+
"data-oods-component": "Combobox",
|
|
3334
|
+
"data-size": props.size,
|
|
3335
|
+
"data-validation-state": props.validation?.state
|
|
3336
|
+
}, [
|
|
3337
|
+
h("label", { id: `${id}-label`, class: "oods-field-label", for: id }, [
|
|
3338
|
+
label,
|
|
3339
|
+
props.required ? h("span", { class: "oods-field-required", "aria-hidden": "true" }, "*") : null
|
|
3340
|
+
]),
|
|
3341
|
+
h("div", { class: "oods-combobox__control" }, [
|
|
3342
|
+
h("input", {
|
|
3343
|
+
id,
|
|
3344
|
+
type: "text",
|
|
3345
|
+
role: "combobox",
|
|
3346
|
+
class: "oods-field-control oods-combobox__input",
|
|
3347
|
+
value: text.value,
|
|
3348
|
+
placeholder: props.placeholder,
|
|
3349
|
+
autocomplete: "off",
|
|
3350
|
+
"aria-autocomplete": "list",
|
|
3351
|
+
"aria-expanded": open.value ? "true" : "false",
|
|
3352
|
+
"aria-controls": `${id}-listbox`,
|
|
3353
|
+
"aria-activedescendant": open.value && active.value >= 0 ? optionId(active.value) : void 0,
|
|
3354
|
+
"aria-describedby": describedBy,
|
|
3355
|
+
"aria-invalid": props.validation?.state === "error" ? "true" : void 0,
|
|
3356
|
+
required: props.required,
|
|
3357
|
+
disabled: props.disabled,
|
|
3358
|
+
onInput: (event) => {
|
|
3359
|
+
query.value = event.target.value;
|
|
3360
|
+
open.value = true;
|
|
3361
|
+
active.value = -1;
|
|
3362
|
+
},
|
|
3363
|
+
onKeydown: keydown,
|
|
3364
|
+
onClick: () => {
|
|
3365
|
+
if (!props.disabled) open.value = true;
|
|
3366
|
+
},
|
|
3367
|
+
onBlur: () => {
|
|
3368
|
+
query.value = null;
|
|
3369
|
+
close();
|
|
3370
|
+
}
|
|
3371
|
+
}),
|
|
3372
|
+
h("span", { class: "oods-combobox__chevron", "aria-hidden": "true" }, [statusIcon("chevron-down")]),
|
|
3373
|
+
h("div", {
|
|
3374
|
+
class: "oods-combobox__popup",
|
|
3375
|
+
hidden: !open.value,
|
|
3376
|
+
onMousedown: (event) => event.preventDefault()
|
|
3377
|
+
}, [
|
|
3378
|
+
h(
|
|
3379
|
+
"ul",
|
|
3380
|
+
{ ref: listbox, id: `${id}-listbox`, class: "oods-combobox__listbox", role: "listbox", "aria-labelledby": `${id}-label` },
|
|
3381
|
+
props.options.map((option, index) => h("li", {
|
|
3382
|
+
key: option.value,
|
|
3383
|
+
id: optionId(index),
|
|
3384
|
+
class: "oods-combobox__option",
|
|
3385
|
+
role: "option",
|
|
3386
|
+
"aria-selected": option.value === chosenValue.value ? "true" : "false",
|
|
3387
|
+
"aria-disabled": option.disabled ? "true" : void 0,
|
|
3388
|
+
"data-value": option.value,
|
|
3389
|
+
"data-active": index === active.value ? "true" : void 0,
|
|
3390
|
+
hidden: !matches.value[index],
|
|
3391
|
+
onClick: () => pick(index),
|
|
3392
|
+
onPointermove: () => {
|
|
3393
|
+
if (!option.disabled && index !== active.value) active.value = index;
|
|
3394
|
+
}
|
|
3395
|
+
}, [
|
|
3396
|
+
h("span", { class: "oods-combobox__option-label" }, option.label),
|
|
3397
|
+
h("span", { class: "oods-combobox__check", "aria-hidden": "true" }, [statusIcon("check")])
|
|
3398
|
+
]))
|
|
3399
|
+
),
|
|
3400
|
+
h("p", { class: "oods-combobox__empty", role: "status" }, noMatches ? "No matches" : "")
|
|
3401
|
+
])
|
|
3402
|
+
]),
|
|
3403
|
+
props.name ? h("input", { type: "hidden", name: props.name, value: chosenValue.value }) : null,
|
|
3404
|
+
help ? h("p", { id: `${id}-help`, class: "oods-field-help" }, help) : null,
|
|
3405
|
+
validation ? h("p", { id: `${id}-validation`, class: "oods-field-error", role: props.validation?.state === "error" ? "alert" : void 0 }, validation) : null
|
|
3406
|
+
]);
|
|
3407
|
+
};
|
|
3408
|
+
}
|
|
3409
|
+
});
|
|
3087
3410
|
|
|
3088
|
-
export { AddressCollectionPanel, AddressEditor, AddressSummaryBadge, AddressValidationTimeline, ArchiveEvent, ArchivePill, ArchiveSummary, ArchivedRowOverlay, AuditEvent, AuditSummaryCard, AuditTimeline, Badge, Banner, BillingAmountInput, BillingCardMeta, BillingIntervalSelector, BillingSummaryBadge, Button, CancellationBadge, CancellationEvent, CancellationForm, CancellationSummary, Card, CardHeader, Checkbox, ClassificationBadge, ClassificationEditor, ClassificationPanel, ColorStatePicker, ColorSwatch, ColorizedBadge, CommunicationDetailPanel, CycleProgressCard, DatePicker, DetailHeader, Dialog, FilterPanel, FormLabelGroup, GeoFieldMappingForm, GeoResolutionBadge, GeocodablePreview, Grid, InlineLabel, Input, LabelCell, MembershipAuditTimeline, MembershipPanel, MessageEventTimeline, MessageStatusBadge, OwnerBadge, OwnershipMeta, OwnershipSummary, PaginationBar, PaymentEventTimeline, PaymentTimeline, PreferenceEditor, PreferencePanel, PreferenceSummaryBadge, PreferenceTimeline, PriceBadge, PriceCardMeta, PriceSummary, RelativeTimestamp, RoleAssignmentForm, RoleBadgeList, SearchInput, Select, SortIndicator, Stack, StateTransitionEvent, StatusBadge, StatusColorLegend, StatusSelector, StatusTimeline, Switch, Table, TableBody, TableCaption, TableCell, TableHead, TableHeaderCell, TableRow, Tabs, TagInput, TagManager, TagPills, TagSummary, TemplatePicker, Text, Textarea, TimelineEntryLabel, VizAreaControls, VizAreaPreview, VizAxisControls, VizAxisSummary, VizColorControls, VizColorLegendConfig, VizEncodingBadge, VizGraphPreview, VizHeatmapControls, VizHeatmapPreview, VizLineControls, VizLinePreview, VizMarkControls, VizMarkPreview, VizOpacityControls, VizOpacitySummary, VizPointControls, VizPointPreview, VizRoleBadge, VizScaleControls, VizScaleSummary, VizScatterControls, VizScatterPreview, VizShapeControls, VizShapeLegend, VizSizeControls, VizSizeSummary };
|
|
3411
|
+
export { AddressCollectionPanel, AddressEditor, AddressSummaryBadge, AddressValidationTimeline, ArchiveEvent, ArchivePill, ArchiveSummary, ArchivedRowOverlay, AuditEvent, AuditSummaryCard, AuditTimeline, Badge, Banner, BillingAmountInput, BillingCardMeta, BillingIntervalSelector, BillingSummaryBadge, Button, CancellationBadge, CancellationEvent, CancellationForm, CancellationSummary, Card, CardHeader, Checkbox, ClassificationBadge, ClassificationEditor, ClassificationPanel, ColorStatePicker, ColorSwatch, ColorizedBadge, Combobox, CommunicationDetailPanel, CycleProgressCard, DatePicker, DetailHeader, Dialog, FilterPanel, FormLabelGroup, GeoFieldMappingForm, GeoResolutionBadge, GeocodablePreview, Grid, InlineLabel, Input, LabelCell, MembershipAuditTimeline, MembershipPanel, MessageEventTimeline, MessageStatusBadge, OwnerBadge, OwnershipMeta, OwnershipSummary, PaginationBar, PaymentEventTimeline, PaymentTimeline, PreferenceEditor, PreferencePanel, PreferenceSummaryBadge, PreferenceTimeline, PriceBadge, PriceCardMeta, PriceSummary, RelativeTimestamp, RoleAssignmentForm, RoleBadgeList, SearchInput, SegmentedControl, Select, SortIndicator, Stack, StateTransitionEvent, StatusBadge, StatusColorLegend, StatusSelector, StatusTimeline, Switch, Table, TableBody, TableCaption, TableCell, TableHead, TableHeaderCell, TableRow, Tabs, TagInput, TagManager, TagPills, TagSummary, TemplatePicker, Text, Textarea, TimelineEntryLabel, VizAreaControls, VizAreaPreview, VizAxisControls, VizAxisSummary, VizColorControls, VizColorLegendConfig, VizEncodingBadge, VizGraphPreview, VizHeatmapControls, VizHeatmapPreview, VizLineControls, VizLinePreview, VizMarkControls, VizMarkPreview, VizOpacityControls, VizOpacitySummary, VizPointControls, VizPointPreview, VizRoleBadge, VizScaleControls, VizScaleSummary, VizScatterControls, VizScatterPreview, VizShapeControls, VizShapeLegend, VizSizeControls, VizSizeSummary };
|
package/dist/ported.cjs
CHANGED
|
@@ -187,6 +187,31 @@ vue.defineComponent({
|
|
|
187
187
|
}
|
|
188
188
|
});
|
|
189
189
|
var canShowModal = () => typeof HTMLDialogElement !== "undefined" && typeof HTMLDialogElement.prototype.showModal === "function";
|
|
190
|
+
var pageLocks = 0;
|
|
191
|
+
var pageStyle;
|
|
192
|
+
function lockPageScroll() {
|
|
193
|
+
const page = document.documentElement;
|
|
194
|
+
if (pageLocks++ === 0) {
|
|
195
|
+
const scrollbar = window.innerWidth - page.clientWidth;
|
|
196
|
+
pageStyle = { overflow: page.style.overflow, paddingRight: page.style.paddingRight };
|
|
197
|
+
if (scrollbar > 0) page.style.paddingRight = `${parseFloat(getComputedStyle(page).paddingRight) + scrollbar}px`;
|
|
198
|
+
page.style.overflow = "hidden";
|
|
199
|
+
}
|
|
200
|
+
let held = true;
|
|
201
|
+
return () => {
|
|
202
|
+
if (!held) return;
|
|
203
|
+
held = false;
|
|
204
|
+
if (--pageLocks === 0 && pageStyle) {
|
|
205
|
+
page.style.overflow = pageStyle.overflow;
|
|
206
|
+
page.style.paddingRight = pageStyle.paddingRight;
|
|
207
|
+
pageStyle = void 0;
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
var outsideBox = (event, dialog) => {
|
|
212
|
+
const box = dialog.getBoundingClientRect();
|
|
213
|
+
return event.clientX < box.left || event.clientX > box.right || event.clientY < box.top || event.clientY > box.bottom;
|
|
214
|
+
};
|
|
190
215
|
vue.defineComponent({
|
|
191
216
|
name: "OodsDialog",
|
|
192
217
|
props: {
|
|
@@ -208,15 +233,24 @@ vue.defineComponent({
|
|
|
208
233
|
const element = vue.ref(null);
|
|
209
234
|
const mounted = vue.ref(false);
|
|
210
235
|
const managed = vue.computed(() => props.modal && mounted.value && canShowModal());
|
|
236
|
+
let unlockScroll;
|
|
237
|
+
let pressedBackdrop = false;
|
|
238
|
+
const releaseScroll = () => {
|
|
239
|
+
unlockScroll?.();
|
|
240
|
+
unlockScroll = void 0;
|
|
241
|
+
};
|
|
211
242
|
const sync = () => {
|
|
212
243
|
const dialog = element.value;
|
|
213
244
|
if (!dialog || !managed.value) return;
|
|
214
|
-
if (props.open && !dialog.open)
|
|
215
|
-
|
|
245
|
+
if (props.open && !dialog.open) {
|
|
246
|
+
dialog.showModal();
|
|
247
|
+
unlockScroll ??= lockPageScroll();
|
|
248
|
+
} else if (!props.open && dialog.open) dialog.close();
|
|
216
249
|
};
|
|
217
250
|
vue.onMounted(() => {
|
|
218
251
|
mounted.value = true;
|
|
219
252
|
});
|
|
253
|
+
vue.onBeforeUnmount(releaseScroll);
|
|
220
254
|
vue.watch([() => props.open, managed], sync, { flush: "post" });
|
|
221
255
|
const requestClose = (event) => {
|
|
222
256
|
event.preventDefault();
|
|
@@ -239,10 +273,23 @@ vue.defineComponent({
|
|
|
239
273
|
if (event.key === "Escape" && !event.defaultPrevented) requestClose(event);
|
|
240
274
|
},
|
|
241
275
|
onCancel: requestClose,
|
|
242
|
-
//
|
|
243
|
-
//
|
|
276
|
+
// A close event from moving a mounted dialog into the top layer finds it open again, and is not reported. Any other
|
|
277
|
+
// close releases the page; when the browser closed it (a close request it would not let be cancelled) while open is
|
|
278
|
+
// still true, it is reported.
|
|
244
279
|
onClose: () => {
|
|
245
|
-
if (
|
|
280
|
+
if (element.value?.open) return;
|
|
281
|
+
releaseScroll();
|
|
282
|
+
if (props.open) emit("close");
|
|
283
|
+
},
|
|
284
|
+
onMousedown: (event) => {
|
|
285
|
+
pressedBackdrop = managed.value && event.target === event.currentTarget && outsideBox(event, event.currentTarget);
|
|
286
|
+
},
|
|
287
|
+
// s223-m02 (#2527 ruling 13b): a click on the backdrop emits close, as the close control does. A press that began
|
|
288
|
+
// inside the dialog (text selected and dragged out) is not a backdrop click.
|
|
289
|
+
onClick: (event) => {
|
|
290
|
+
const backdrop = pressedBackdrop && event.target === event.currentTarget && outsideBox(event, event.currentTarget);
|
|
291
|
+
pressedBackdrop = false;
|
|
292
|
+
if (backdrop) emit("close");
|
|
246
293
|
}
|
|
247
294
|
}, [
|
|
248
295
|
vue.h("div", { class: "oods-dialog__header" }, [
|
|
@@ -1063,12 +1110,15 @@ var CancellationSummary = vue.defineComponent({
|
|
|
1063
1110
|
cancelAtPeriodEndField: String,
|
|
1064
1111
|
requestedAtField: String,
|
|
1065
1112
|
reasonField: String,
|
|
1066
|
-
codeField: String
|
|
1113
|
+
codeField: String,
|
|
1114
|
+
// s224-m01 (#2542 ruling 6): Boolean first, as the badges' hideWhenFalse is (a bare attribute casts to true).
|
|
1115
|
+
hideWhenDefault: { type: [Boolean, String], default: void 0 }
|
|
1067
1116
|
},
|
|
1068
1117
|
setup(props, { attrs, slots }) {
|
|
1069
1118
|
return () => {
|
|
1070
1119
|
const slotValue = slotSummaryValue(slots);
|
|
1071
1120
|
const cancellationValue = props.cancelAtPeriodEnd ?? slotValue;
|
|
1121
|
+
if (props.hideWhenDefault === true && props.cancelAtPeriodEnd === false && !props.requestedAt && !props.reason && !props.code && slotValue === void 0) return null;
|
|
1072
1122
|
const rows = [];
|
|
1073
1123
|
if (cancellationValue !== void 0) {
|
|
1074
1124
|
rows.push(summaryEntry(
|
package/dist/ported.d.cts
CHANGED
|
@@ -401,9 +401,13 @@ declare const CancellationSummary: vue.DefineComponent<vue.ExtractPropTypes<{
|
|
|
401
401
|
requestedAtField: StringConstructor;
|
|
402
402
|
reasonField: StringConstructor;
|
|
403
403
|
codeField: StringConstructor;
|
|
404
|
+
hideWhenDefault: {
|
|
405
|
+
type: (StringConstructor | BooleanConstructor)[];
|
|
406
|
+
default: undefined;
|
|
407
|
+
};
|
|
404
408
|
}>, () => VNode<vue.RendererNode, vue.RendererElement, {
|
|
405
409
|
[key: string]: any;
|
|
406
|
-
}
|
|
410
|
+
}> | null, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<vue.ExtractPropTypes<{
|
|
407
411
|
title: StringConstructor;
|
|
408
412
|
label: StringConstructor;
|
|
409
413
|
cancelAtPeriodEnd: {
|
|
@@ -418,8 +422,13 @@ declare const CancellationSummary: vue.DefineComponent<vue.ExtractPropTypes<{
|
|
|
418
422
|
requestedAtField: StringConstructor;
|
|
419
423
|
reasonField: StringConstructor;
|
|
420
424
|
codeField: StringConstructor;
|
|
425
|
+
hideWhenDefault: {
|
|
426
|
+
type: (StringConstructor | BooleanConstructor)[];
|
|
427
|
+
default: undefined;
|
|
428
|
+
};
|
|
421
429
|
}>> & Readonly<{}>, {
|
|
422
430
|
cancelAtPeriodEnd: boolean;
|
|
431
|
+
hideWhenDefault: string | boolean;
|
|
423
432
|
}, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
|
|
424
433
|
declare const SearchInput: vue.DefineComponent<vue.ExtractPropTypes<{
|
|
425
434
|
id: StringConstructor;
|
package/dist/ported.d.ts
CHANGED
|
@@ -401,9 +401,13 @@ declare const CancellationSummary: vue.DefineComponent<vue.ExtractPropTypes<{
|
|
|
401
401
|
requestedAtField: StringConstructor;
|
|
402
402
|
reasonField: StringConstructor;
|
|
403
403
|
codeField: StringConstructor;
|
|
404
|
+
hideWhenDefault: {
|
|
405
|
+
type: (StringConstructor | BooleanConstructor)[];
|
|
406
|
+
default: undefined;
|
|
407
|
+
};
|
|
404
408
|
}>, () => VNode<vue.RendererNode, vue.RendererElement, {
|
|
405
409
|
[key: string]: any;
|
|
406
|
-
}
|
|
410
|
+
}> | null, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<vue.ExtractPropTypes<{
|
|
407
411
|
title: StringConstructor;
|
|
408
412
|
label: StringConstructor;
|
|
409
413
|
cancelAtPeriodEnd: {
|
|
@@ -418,8 +422,13 @@ declare const CancellationSummary: vue.DefineComponent<vue.ExtractPropTypes<{
|
|
|
418
422
|
requestedAtField: StringConstructor;
|
|
419
423
|
reasonField: StringConstructor;
|
|
420
424
|
codeField: StringConstructor;
|
|
425
|
+
hideWhenDefault: {
|
|
426
|
+
type: (StringConstructor | BooleanConstructor)[];
|
|
427
|
+
default: undefined;
|
|
428
|
+
};
|
|
421
429
|
}>> & Readonly<{}>, {
|
|
422
430
|
cancelAtPeriodEnd: boolean;
|
|
431
|
+
hideWhenDefault: string | boolean;
|
|
423
432
|
}, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
|
|
424
433
|
declare const SearchInput: vue.DefineComponent<vue.ExtractPropTypes<{
|
|
425
434
|
id: StringConstructor;
|