bitboss-ui 3.0.0-beta.21 → 3.0.0-beta.23
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 +55 -3
- package/bin/bitboss-ui-mcp.mjs +419 -9
- package/bin/bitboss-ui.mjs +293 -22
- package/dist/ai/BbAccordion.md +21 -23
- package/dist/ai/BbAlert.md +6 -12
- package/dist/ai/BbAvatar.md +60 -24
- package/dist/ai/BbBadge.md +12 -20
- package/dist/ai/BbBaseButton.md +14 -16
- package/dist/ai/BbBaseCheckboxIcon.md +6 -10
- package/dist/ai/BbBaseColorInput.md +1 -0
- package/dist/ai/BbBaseDatePickerInput.md +1 -0
- package/dist/ai/BbBaseNumberInput.md +1 -0
- package/dist/ai/BbBaseRadioIcon.md +6 -10
- package/dist/ai/BbBaseSelect.md +1 -0
- package/dist/ai/BbBaseSwitchIcon.md +5 -9
- package/dist/ai/BbBaseTag.md +1 -0
- package/dist/ai/BbBaseTextInput.md +2 -1
- package/dist/ai/BbBaseTextarea.md +1 -0
- package/dist/ai/BbBaseTimePickerInput.md +1 -0
- package/dist/ai/BbBreadcrumbs.md +23 -34
- package/dist/ai/BbButton.md +35 -47
- package/dist/ai/BbCheckbox.md +21 -37
- package/dist/ai/BbCheckboxGroup.md +13 -13
- package/dist/ai/BbCollapsible.md +14 -26
- package/dist/ai/BbColorInput.md +27 -23
- package/dist/ai/BbColorPalette.md +23 -35
- package/dist/ai/BbConfirm.md +17 -32
- package/dist/ai/BbDatePickerInput.md +29 -21
- package/dist/ai/BbDialog.md +159 -62
- package/dist/ai/BbDropdown.md +21 -25
- package/dist/ai/BbDropdownButton.md +13 -30
- package/dist/ai/BbDropzone.md +9 -11
- package/dist/ai/BbIcon.md +44 -33
- package/dist/ai/BbIndicator.md +2 -2
- package/dist/ai/BbNumberInput.md +32 -20
- package/dist/ai/BbOffCanvas.md +42 -42
- package/dist/ai/BbPagination.md +21 -23
- package/dist/ai/BbPopover.md +15 -17
- package/dist/ai/BbProgress.md +40 -51
- package/dist/ai/BbRadio.md +9 -9
- package/dist/ai/BbRadioGroup.md +7 -11
- package/dist/ai/BbRating.md +8 -12
- package/dist/ai/BbSelect.md +46 -36
- package/dist/ai/BbSelectPopover.md +19 -31
- package/dist/ai/BbSlider.md +15 -19
- package/dist/ai/BbSmoothHeight.md +16 -31
- package/dist/ai/BbSpinner.md +118 -74
- package/dist/ai/BbSwitch.md +25 -18
- package/dist/ai/BbSwitchGroup.md +9 -14
- package/dist/ai/BbTable.md +102 -55
- package/dist/ai/BbTabs.md +59 -82
- package/dist/ai/BbTag.md +26 -23
- package/dist/ai/BbTextInput.md +63 -27
- package/dist/ai/BbTextarea.md +42 -34
- package/dist/ai/BbTimePickerInput.md +14 -0
- package/dist/ai/BbToast.md +14 -34
- package/dist/ai/BbTooltip.md +22 -20
- package/dist/ai/BbTree.md +46 -72
- package/dist/ai/CommonInputWrapper.md +1 -0
- package/dist/ai/changelog.json +170 -62
- package/dist/ai/components.json +1678 -11
- package/dist/ai/composables/useConfirm.md +5 -2
- package/dist/ai/composables/useToast.md +4 -2
- package/dist/ai/guides/agent-contract.md +7 -4
- package/dist/ai/guides/ai-router.md +37 -22
- package/dist/ai/guides/component-picker.md +23 -18
- package/dist/ai/guides/design-language.md +151 -21
- package/dist/ai/guides/design-tokens.md +29 -4
- package/dist/ai/guides/icons-policy.md +46 -21
- package/dist/ai/guides/installation-and-plugin-setup.md +286 -17
- package/dist/ai/guides/migration/components/bb-rating.md +26 -1
- package/dist/ai/guides/migration/components/bb-tooltip.md +18 -0
- package/dist/ai/guides/migration/v2-to-v3.md +50 -23
- package/dist/ai/index.md +1 -1
- package/dist/ai/recipes/inertia/approvals-inbox.md +3 -3
- package/dist/ai/recipes/inertia/inline-edit-workspace.md +2 -2
- package/dist/ai/recipes/inertia/onboarding.md +2 -2
- package/dist/ai/recipes/inertia/ownership-atlas.md +6 -6
- package/dist/ai/recipes/inertia/record-form.md +5 -5
- package/dist/ai/recipes/inertia/records-workspace.md +4 -4
- package/dist/ai/recipes/inertia/upload-center.md +6 -6
- package/dist/ai/recipes/inertia/wizard-form.md +5 -5
- package/dist/ai/recipes/nuxt/approvals-inbox.md +3 -3
- package/dist/ai/recipes/nuxt/inline-edit-workspace.md +2 -2
- package/dist/ai/recipes/nuxt/onboarding.md +2 -2
- package/dist/ai/recipes/nuxt/record-form.md +5 -5
- package/dist/ai/recipes/nuxt/records-workspace.md +4 -4
- package/dist/ai/recipes/nuxt/upload-center.md +6 -6
- package/dist/ai/recipes/nuxt/wizard-form.md +5 -5
- package/dist/ai/recipes/vue/approvals-inbox.md +3 -3
- package/dist/ai/recipes/vue/inline-edit-workspace.md +2 -2
- package/dist/ai/recipes/vue/onboarding.md +2 -2
- package/dist/ai/recipes/vue/record-form.md +10 -10
- package/dist/ai/recipes/vue/records-workspace.md +4 -4
- package/dist/ai/recipes/vue/upload-center.md +6 -6
- package/dist/ai/recipes/vue/wizard-form.md +5 -5
- package/dist/ai/source/BbBadge.md +1 -1
- package/dist/ai/source/BbBaseCheckbox.md +1 -1
- package/dist/ai/source/BbBaseColorInput.md +7 -0
- package/dist/ai/source/BbBaseDatePicker.md +5 -5
- package/dist/ai/source/BbBaseDatePickerInput.md +9 -2
- package/dist/ai/source/BbBaseNumberInput.md +7 -0
- package/dist/ai/source/BbBaseRadio.md +1 -1
- package/dist/ai/source/BbBaseRating.md +5 -5
- package/dist/ai/source/BbBaseSelect.md +8 -1
- package/dist/ai/source/BbBaseSlider.md +5 -5
- package/dist/ai/source/BbBaseSwitch.md +1 -1
- package/dist/ai/source/BbBaseTag.md +7 -0
- package/dist/ai/source/BbBaseTextInput.md +7 -0
- package/dist/ai/source/BbBaseTextarea.md +7 -0
- package/dist/ai/source/BbBaseTimePickerInput.md +8 -1
- package/dist/ai/source/BbBreadcrumbs.md +20 -1
- package/dist/ai/source/BbButton.md +2 -2
- package/dist/ai/source/BbColorInput.md +14 -0
- package/dist/ai/source/BbDatePickerInput.md +14 -0
- package/dist/ai/source/BbDialog.md +39 -8
- package/dist/ai/source/BbDropdown.md +1 -1
- package/dist/ai/source/BbDropzone.md +5 -5
- package/dist/ai/source/BbIcon.md +23 -10
- package/dist/ai/source/BbNumberInput.md +14 -0
- package/dist/ai/source/BbOffCanvas.md +50 -28
- package/dist/ai/source/BbPagination.md +2 -2
- package/dist/ai/source/BbPopover.md +12 -1
- package/dist/ai/source/BbSelect.md +14 -0
- package/dist/ai/source/BbSelectPopover.md +45 -7
- package/dist/ai/source/BbSpinner.md +2 -2
- package/dist/ai/source/BbTable.md +11 -11
- package/dist/ai/source/BbTag.md +14 -0
- package/dist/ai/source/BbTextInput.md +14 -0
- package/dist/ai/source/BbTextarea.md +14 -0
- package/dist/ai/source/BbTimePickerInput.md +14 -0
- package/dist/ai/source/BbTooltip.md +57 -10
- package/dist/ai/source/ChipsBox.md +1 -1
- package/dist/ai/source/CommaBox.md +1 -1
- package/dist/ai/source/CommonInputWrapper.md +128 -33
- package/dist/ai/source/GuidesComponent.md +14 -7
- package/dist/ai/source/OptionsContainer.md +1 -1
- package/dist/components/BbBadge/BadgeBodyContent.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/BbBadge/BbBadge.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/BbBaseCheckbox/BbBaseCheckbox.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/BbBaseColorInput/BbBaseColorInput.vue_vue_type_script_setup_true_lang.js +4 -1
- package/dist/components/BbBaseColorInput/types.d.ts +5 -0
- package/dist/components/BbBaseDatePicker/BbBaseDatePicker.vue_vue_type_script_setup_true_lang.js +4 -4
- package/dist/components/BbBaseDatePicker/BbBaseDatePickerInputDaySelector.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/BbBaseDatePickerInput/BbBaseDatePickerInput.vue_vue_type_script_setup_true_lang.js +5 -2
- package/dist/components/BbBaseDatePickerInput/types.d.ts +5 -0
- package/dist/components/BbBaseInputContainer/BbBaseInputContainer.vue.d.ts +1 -1
- package/dist/components/BbBaseNumberInput/BbBaseNumberInput.vue_vue_type_script_setup_true_lang.js +4 -1
- package/dist/components/BbBaseNumberInput/types.d.ts +5 -0
- package/dist/components/BbBaseRadio/BbBaseRadio.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/BbBaseRating/BbBaseRating.vue_vue_type_script_setup_true_lang.js +3 -3
- package/dist/components/BbBaseSelect/BbBaseSelect.vue_vue_type_script_setup_true_lang.js +4 -1
- package/dist/components/BbBaseSelect/types.d.ts +5 -0
- package/dist/components/BbBaseSlider/BbBaseSlider.vue_vue_type_script_setup_true_lang.js +3 -3
- package/dist/components/BbBaseSwitch/BbBaseSwitch.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/BbBaseTag/BbBaseTag.vue_vue_type_script_setup_true_lang.js +4 -1
- package/dist/components/BbBaseTag/types.d.ts +5 -0
- package/dist/components/BbBaseTextInput/BbBaseTextInput.vue_vue_type_script_setup_true_lang.js +4 -1
- package/dist/components/BbBaseTextInput/types.d.ts +5 -0
- package/dist/components/BbBaseTextarea/BbBaseTextarea.vue_vue_type_script_setup_true_lang.js +4 -1
- package/dist/components/BbBaseTextarea/types.d.ts +5 -0
- package/dist/components/BbBaseTimePickerInput/BbBaseTimePickerInput.vue_vue_type_script_setup_true_lang.js +5 -2
- package/dist/components/BbBaseTimePickerInput/types.d.ts +5 -0
- package/dist/components/BbBreadcrumbs/BbBreadcrumbs.vue_vue_type_script_setup_true_lang.js +71 -71
- package/dist/components/BbButton/BbButton.vue_vue_type_script_setup_true_lang.js +2 -2
- package/dist/components/BbColorInput/BbColorInput.vue_vue_type_script_setup_true_lang.js +5 -2
- package/dist/components/BbColorInput/types.d.ts +12 -0
- package/dist/components/BbDatePickerInput/BbDatePickerInput.vue_vue_type_script_setup_true_lang.js +4 -2
- package/dist/components/BbDatePickerInput/types.d.ts +12 -0
- package/dist/components/BbDialog/BbDialog.vue_vue_type_script_setup_true_lang.js +102 -97
- package/dist/components/BbDropdown/AdaptiveDropdown.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/BbDropdown/BbDropdown.vue_vue_type_script_setup_true_lang.js +58 -58
- package/dist/components/BbDropzone/BbDropzone.vue_vue_type_script_setup_true_lang.js +2 -2
- package/dist/components/BbIcon/BbIcon.vue_vue_type_script_setup_true_lang.js +33 -35
- package/dist/components/BbIcon/iconCache.d.ts +30 -0
- package/dist/components/BbIcon/iconCache.js +21 -3
- package/dist/components/BbNumberInput/BbNumberInput.vue_vue_type_script_setup_true_lang.js +5 -2
- package/dist/components/BbNumberInput/types.d.ts +12 -0
- package/dist/components/BbOffCanvas/BbOffCanvas.vue_vue_type_script_setup_true_lang.js +57 -56
- package/dist/components/BbPagination/BbPagination.vue_vue_type_script_setup_true_lang.js +2 -2
- package/dist/components/BbPopover/BbPopover.vue_vue_type_script_setup_true_lang.js +138 -138
- package/dist/components/BbSelect/BbSelect.vue_vue_type_script_setup_true_lang.js +4 -2
- package/dist/components/BbSelect/types.d.ts +12 -0
- package/dist/components/BbSelectPopover/BbSelectPopover.vue_vue_type_script_setup_true_lang.js +43 -43
- package/dist/components/BbSpinner/BbSpinner.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/BbSpinner/types.d.ts +1 -1
- package/dist/components/BbTable/BbTable.vue_vue_type_script_setup_true_lang.js +8 -8
- package/dist/components/BbTable/BbTableDataRow.js +2 -2
- package/dist/components/BbTag/BbTag.vue_vue_type_script_setup_true_lang.js +5 -2
- package/dist/components/BbTag/types.d.ts +12 -0
- package/dist/components/BbTextInput/BbTextInput.vue_vue_type_script_setup_true_lang.js +5 -2
- package/dist/components/BbTextInput/types.d.ts +12 -0
- package/dist/components/BbTextarea/BbTextarea.vue_vue_type_script_setup_true_lang.js +5 -2
- package/dist/components/BbTextarea/types.d.ts +12 -0
- package/dist/components/BbTimePickerInput/BbTimePickerInput.vue_vue_type_script_setup_true_lang.js +4 -2
- package/dist/components/BbTimePickerInput/types.d.ts +12 -0
- package/dist/components/BbToast/BbToastRegion.vue_vue_type_script_setup_true_lang.js +62 -62
- package/dist/components/BbTooltip/BbTooltip.vue_vue_type_script_setup_true_lang.js +81 -78
- package/dist/components/BbTooltip/types.d.ts +8 -1
- package/dist/components/ChipsBox/ChipsBox.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/CommaBox/CommaBox.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/CommonInputWrapper/CommonInputWrapper.vue.d.ts +1 -0
- package/dist/components/CommonInputWrapper/CommonInputWrapper.vue_vue_type_script_setup_true_lang.js +4 -2
- package/dist/components/CommonInputWrapper/types.d.ts +10 -0
- package/dist/components/OptionsContainer/OptionsContainer.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/composables/useConfirm.d.ts +22 -0
- package/dist/composables/useConfirm.js +43 -40
- package/dist/composables/useSafeAreaInternal.js +1 -1
- package/dist/composables/useToast.d.ts +16 -0
- package/dist/composables/useToast.js +20 -16
- package/dist/composables/useViewportWidth.d.ts +20 -6
- package/dist/composables/useViewportWidth.js +8 -7
- package/dist/icon-scan.d.ts +276 -0
- package/dist/icon-scan.js +485 -0
- package/dist/icons-whitelist.d.ts +5 -4
- package/dist/index.d.ts +2 -0
- package/dist/input-variants.d.ts +18 -0
- package/dist/llms-full.txt +2173 -1537
- package/dist/llms-medium.txt +504 -82
- package/dist/llms.txt +1 -1
- package/dist/nuxt-module.d.ts +1 -0
- package/dist/nuxt.js +10 -7
- package/dist/plugin.js +1 -0
- package/dist/runtime/nuxt-plugin.js +2 -1
- package/dist/styles.css +1 -1
- package/dist/types/Config.d.ts +18 -0
- package/dist/types/InputVariant.d.ts +22 -0
- package/dist/utils/cssLayers.d.ts +91 -0
- package/dist/utils/cssLayers.js +43 -0
- package/dist/utils/injectLibraryStyles.d.ts +3 -1
- package/dist/utils/injectLibraryStyles.js +24 -23
- package/dist/validated/BbColorInput.vue_vue_type_script_setup_true_lang.js +1 -0
- package/dist/validated/BbDatePickerInput.vue_vue_type_script_setup_true_lang.js +1 -0
- package/dist/validated/BbNumberInput.vue_vue_type_script_setup_true_lang.js +1 -0
- package/dist/validated/BbSelect.vue_vue_type_script_setup_true_lang.js +1 -0
- package/dist/validated/BbTag.vue_vue_type_script_setup_true_lang.js +1 -0
- package/dist/validated/BbTextInput.vue_vue_type_script_setup_true_lang.js +1 -0
- package/dist/validated/BbTextarea.vue_vue_type_script_setup_true_lang.js +1 -0
- package/dist/validated/BbTimePickerInput.vue_vue_type_script_setup_true_lang.js +1 -0
- package/dist/validated/index.d.ts +1 -0
- package/dist/vite-plugin.d.ts +89 -12
- package/dist/vite.js +331 -281
- package/llms.txt +1 -1
- package/package.json +7 -5
- package/scripts/lib/ensure-manifest.mjs +28 -5
- package/scripts/lib/eslint-plugin.d.ts +35 -0
- package/scripts/lib/eslint-plugin.mjs +299 -3
- package/scripts/lib/hand-roll-hints.mjs +50 -6
- package/scripts/lib/html-attributes.mjs +42 -0
- package/scripts/lib/mcp-config.mjs +38 -34
- package/scripts/lib/public-type-exports.mjs +246 -0
- package/scripts/lib/validate-bb-markup.mjs +205 -12
|
@@ -9,8 +9,12 @@ var { t: s } = n(), c = e(), l = [], u = {
|
|
|
9
9
|
yesBusy: !1,
|
|
10
10
|
noBusy: !1,
|
|
11
11
|
actionBusy: null
|
|
12
|
-
}, d = o({ ...u }), f = d, p = a(/* @__PURE__ */ new Map()), m = (e, t) => (p.set(e, t), () => p.delete(e)), h = t.medium, g, _, v = 0, y = !1, b =
|
|
13
|
-
|
|
12
|
+
}, d = o({ ...u }), f = d, p = a(/* @__PURE__ */ new Map()), m = (e, t) => (p.set(e, t), () => p.delete(e)), h = t.medium, g, _, v = 0, y = !1, b, x = 1e3, S = (e) => {
|
|
13
|
+
process.env.NODE_ENV === "production" || y || (clearTimeout(b), b = setTimeout(() => {
|
|
14
|
+
y || v > 0 || e() || (y = !0, c.warn("Confirm: confirm() was called but no <BbConfirm> host is mounted — the returned promise will never settle because no dialog can render. Mount exactly one <BbConfirm /> at the app root."));
|
|
15
|
+
}, x));
|
|
16
|
+
}, C = () => {
|
|
17
|
+
v++, clearTimeout(b);
|
|
14
18
|
let e = !1;
|
|
15
19
|
return {
|
|
16
20
|
count: v,
|
|
@@ -18,36 +22,36 @@ var { t: s } = n(), c = e(), l = [], u = {
|
|
|
18
22
|
e || (e = !0, v--);
|
|
19
23
|
}
|
|
20
24
|
};
|
|
21
|
-
},
|
|
25
|
+
}, w = () => {
|
|
22
26
|
clearTimeout(_), clearTimeout(g), d.value = { ...u };
|
|
23
|
-
},
|
|
27
|
+
}, T = () => {
|
|
24
28
|
let e = l.shift();
|
|
25
29
|
if (!e) return;
|
|
26
30
|
let t = d.value.current;
|
|
27
|
-
t && !t.settled && t.resolve(!1),
|
|
31
|
+
t && !t.settled && t.resolve(!1), w(), d.value.current = e, d.value.processing = !0, process.env.NODE_ENV !== "production" && !e.title && !e.text && !e.portal && console.warn("[BbConfirm] A confirm was opened with no title, text, or portal — the dialog will appear empty."), process.env.NODE_ENV !== "production" && e.text && e.portal && c.warn("Confirm: a message carries both `text` and `portal` — `text` takes priority and the portal is ignored. Remove one of the two."), e.duration && (d.value.current.autoClose = !0, g = setTimeout(() => {
|
|
28
32
|
let { current: e } = d.value;
|
|
29
|
-
e && (
|
|
33
|
+
e && (E(e), l.length ? T() : k());
|
|
30
34
|
}, e.duration));
|
|
31
|
-
},
|
|
35
|
+
}, E = (e) => {
|
|
32
36
|
e.settled || e.resolve(!1);
|
|
33
|
-
},
|
|
34
|
-
for (let t = l.length - 1; t >= 0; t--) l[t].owner === e && (
|
|
37
|
+
}, D = (e) => {
|
|
38
|
+
for (let t = l.length - 1; t >= 0; t--) l[t].owner === e && (E(l[t]), l.splice(t, 1));
|
|
35
39
|
let { current: t } = d.value;
|
|
36
|
-
t?.owner === e && (
|
|
37
|
-
},
|
|
38
|
-
for (; l.length;)
|
|
40
|
+
t?.owner === e && (E(t), l.length ? T() : k());
|
|
41
|
+
}, O = () => {
|
|
42
|
+
for (; l.length;) E(l.pop());
|
|
39
43
|
let { current: e } = d.value;
|
|
40
|
-
e && (
|
|
41
|
-
},
|
|
42
|
-
process.env.NODE_ENV !== "production" && d.value.current && !d.value.current.settled && c.warn("Confirm: close() was called while the current confirm() promise is still pending. The dialog is hidden, but the promise will never settle — resolve it first via the Yes/No buttons or the portal yes()/no() helpers."), clearTimeout(g), d.value.yesBusy = !1, d.value.noBusy = !1, d.value.actionBusy = null, d.value.processing = !1, clearTimeout(_), _ = setTimeout(
|
|
43
|
-
},
|
|
44
|
+
e && (E(e), k());
|
|
45
|
+
}, k = () => {
|
|
46
|
+
process.env.NODE_ENV !== "production" && d.value.current && !d.value.current.settled && c.warn("Confirm: close() was called while the current confirm() promise is still pending. The dialog is hidden, but the promise will never settle — resolve it first via the Yes/No buttons or the portal yes()/no() helpers."), clearTimeout(g), d.value.yesBusy = !1, d.value.noBusy = !1, d.value.actionBusy = null, d.value.processing = !1, clearTimeout(_), _ = setTimeout(w, h);
|
|
47
|
+
}, A = (e, t) => {
|
|
44
48
|
typeof e == "number" ? d.value.actionBusy = t ? e : null : e === "yes" ? d.value.yesBusy = t : d.value.noBusy = t;
|
|
45
|
-
},
|
|
49
|
+
}, j = async (e, t = !1) => {
|
|
46
50
|
let { current: n } = d.value;
|
|
47
|
-
n && (clearTimeout(g), e ? n.yes ? await n.yes.onClick() :
|
|
48
|
-
},
|
|
49
|
-
e.resolve(t), l.length ?
|
|
50
|
-
},
|
|
51
|
+
n && (clearTimeout(g), e ? n.yes ? await n.yes.onClick() : M(n, !0) : (t || n.dismissAsNo) && n.no ? await n.no.onClick() : M(n, !1));
|
|
52
|
+
}, M = (e, t) => {
|
|
53
|
+
e.resolve(t), l.length ? T() : e.autoClose && k();
|
|
54
|
+
}, N = (e, t) => {
|
|
51
55
|
if (t === !1) return;
|
|
52
56
|
if (t === void 0) return e;
|
|
53
57
|
let n = typeof t == "string" ? { text: t } : t;
|
|
@@ -58,12 +62,11 @@ var { t: s } = n(), c = e(), l = [], u = {
|
|
|
58
62
|
variant: n.variant ?? e.variant,
|
|
59
63
|
size: n.size ?? e.size
|
|
60
64
|
};
|
|
61
|
-
},
|
|
65
|
+
}, P = (e, t) => new Promise((n, r) => {
|
|
62
66
|
if (typeof window > "u") {
|
|
63
67
|
process.env.NODE_ENV !== "production" && console.warn("[BbConfirm] confirm() was called during server-side rendering — resolved `false`. Trigger confirms from client-side code (event handlers)."), n(!1);
|
|
64
68
|
return;
|
|
65
69
|
}
|
|
66
|
-
process.env.NODE_ENV !== "production" && !y && !b && (b = !0, c.warn("Confirm: confirm() was called but no <BbConfirm> host has ever mounted — the returned promise will never settle because no dialog can render. Mount exactly one <BbConfirm /> at the app root."));
|
|
67
70
|
let i = (e) => {
|
|
68
71
|
m.settled = !0, n(e);
|
|
69
72
|
}, a = (e) => {
|
|
@@ -74,18 +77,18 @@ var { t: s } = n(), c = e(), l = [], u = {
|
|
|
74
77
|
return {
|
|
75
78
|
...e,
|
|
76
79
|
onClick: async () => {
|
|
77
|
-
|
|
80
|
+
A(t, !0);
|
|
78
81
|
let e = n;
|
|
79
82
|
try {
|
|
80
83
|
if (r) {
|
|
81
84
|
let t = await r();
|
|
82
85
|
d && (e = t);
|
|
83
86
|
}
|
|
84
|
-
i(e), l.length ?
|
|
87
|
+
i(e), l.length ? T() : u && k();
|
|
85
88
|
} catch (e) {
|
|
86
|
-
a(e),
|
|
89
|
+
a(e), k();
|
|
87
90
|
} finally {
|
|
88
|
-
|
|
91
|
+
A(t, !1);
|
|
89
92
|
}
|
|
90
93
|
}
|
|
91
94
|
};
|
|
@@ -95,16 +98,16 @@ var { t: s } = n(), c = e(), l = [], u = {
|
|
|
95
98
|
dismissAsNo: !0,
|
|
96
99
|
autoClose: !0,
|
|
97
100
|
...e,
|
|
98
|
-
actions: p ? p.map((e, t) => f(
|
|
101
|
+
actions: p ? p.map((e, t) => f(N({
|
|
99
102
|
size: "md",
|
|
100
103
|
variant: "outline"
|
|
101
104
|
}, e), t, !0)) : e.actions,
|
|
102
|
-
yes: p ? void 0 : f(
|
|
105
|
+
yes: p ? void 0 : f(N({
|
|
103
106
|
text: s("confirm.ok").value,
|
|
104
107
|
size: "md",
|
|
105
108
|
variant: o
|
|
106
109
|
}, e.yes), "yes", !0),
|
|
107
|
-
no: p ? void 0 : f(
|
|
110
|
+
no: p ? void 0 : f(N({
|
|
108
111
|
text: s("confirm.cancel").value,
|
|
109
112
|
size: "md",
|
|
110
113
|
variant: "outline"
|
|
@@ -114,19 +117,19 @@ var { t: s } = n(), c = e(), l = [], u = {
|
|
|
114
117
|
settled: !1,
|
|
115
118
|
owner: t
|
|
116
119
|
};
|
|
117
|
-
l.push(m),
|
|
118
|
-
}),
|
|
120
|
+
l.push(m), v === 0 && S(() => m.settled), T();
|
|
121
|
+
}), F = () => {
|
|
119
122
|
if (!r()) return {
|
|
120
|
-
confirm:
|
|
121
|
-
close:
|
|
122
|
-
dismissAll:
|
|
123
|
+
confirm: P,
|
|
124
|
+
close: k,
|
|
125
|
+
dismissAll: O
|
|
123
126
|
};
|
|
124
127
|
let e = Symbol("bb-confirm-owner");
|
|
125
|
-
return i(() =>
|
|
126
|
-
confirm: (t) =>
|
|
127
|
-
close:
|
|
128
|
-
dismissAll:
|
|
128
|
+
return i(() => D(e)), {
|
|
129
|
+
confirm: (t) => P(t, e),
|
|
130
|
+
close: k,
|
|
131
|
+
dismissAll: O
|
|
129
132
|
};
|
|
130
133
|
};
|
|
131
134
|
//#endregion
|
|
132
|
-
export { h as TRANSITION_DURATION,
|
|
135
|
+
export { x as NO_HOST_WARNING_DELAY, h as TRANSITION_DURATION, C as __registerConfirmHost, f as confirmState, p as namedPortalRegistry, j as processMessage, m as registerNamedPortal, F as useConfirm };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useMobile as e } from "./useMobile.js";
|
|
2
|
-
import {
|
|
2
|
+
import { viewportClientHeight as t, viewportClientWidth as n } from "./useViewportWidth.js";
|
|
3
3
|
import { useOffCanvasStack as r } from "../components/BbOffCanvas/useOffCanvasStack.js";
|
|
4
4
|
import { computed as i, ref as a } from "vue";
|
|
5
5
|
//#region src/composables/useSafeAreaInternal.ts
|
|
@@ -3,6 +3,22 @@ import { BbToast, BbToastDismissReason, BbToastOptions, BbToastPortalContext, Bb
|
|
|
3
3
|
export declare const toastState: {
|
|
4
4
|
toasts: BbToast[];
|
|
5
5
|
};
|
|
6
|
+
/**
|
|
7
|
+
* Grace period before the zero-host warning fires. See the twin in
|
|
8
|
+
* `useConfirm.ts` for the full rationale — the short version: a host mounted
|
|
9
|
+
* in a layout rather than the app root unmounts and remounts across a route
|
|
10
|
+
* change, and a `toast()` landing in that gap is NOT lost. A late-mounting
|
|
11
|
+
* host renders the queued message (verified), so "no host right now" does not
|
|
12
|
+
* mean "no host is coming".
|
|
13
|
+
*
|
|
14
|
+
* At fire time we re-read the count, so the delay only has to outlast a slow
|
|
15
|
+
* async layout chunk; a generous value is strictly safer than a tight one.
|
|
16
|
+
*
|
|
17
|
+
* Supersedes the 2026-07-30 `hostEverMounted` latch, which went quiet for the
|
|
18
|
+
* whole process once ANY host had ever mounted — silencing exactly the case a
|
|
19
|
+
* non-root host produces.
|
|
20
|
+
*/
|
|
21
|
+
export declare const NO_HOST_WARNING_DELAY = 1000;
|
|
6
22
|
/**
|
|
7
23
|
* Called by `<BbToast>` on mount. Internal — not re-exported from
|
|
8
24
|
* `src/index.ts`. Returns the host count including this one (for the
|
|
@@ -7,8 +7,12 @@ var r = 300, i = /* @__PURE__ */ new Set([
|
|
|
7
7
|
"info",
|
|
8
8
|
"warning",
|
|
9
9
|
"destructive"
|
|
10
|
-
]), a = t({ toasts: [] }), o = 0, s = !1, c =
|
|
11
|
-
|
|
10
|
+
]), a = t({ toasts: [] }), o = 0, s = !1, c, l = 1e3, u = () => {
|
|
11
|
+
process.env.NODE_ENV === "production" || s || (clearTimeout(c), c = setTimeout(() => {
|
|
12
|
+
s || o > 0 || (s = !0, console.warn("[BbToast] toast() was called but no <BbToast> host is mounted — the toast is queued but nothing will render or expire it. Mount exactly one <BbToast /> at the app root."));
|
|
13
|
+
}, l));
|
|
14
|
+
}, d = () => {
|
|
15
|
+
o++, clearTimeout(c);
|
|
12
16
|
let e = !1;
|
|
13
17
|
return {
|
|
14
18
|
count: o,
|
|
@@ -16,9 +20,9 @@ var r = 300, i = /* @__PURE__ */ new Set([
|
|
|
16
20
|
e || (e = !0, o--);
|
|
17
21
|
}
|
|
18
22
|
};
|
|
19
|
-
},
|
|
23
|
+
}, f = t(/* @__PURE__ */ new Map()), p = (e, t) => (f.set(e, t), () => f.delete(e)), m = 0, h = (e) => {
|
|
20
24
|
if (e.duration !== void 0 && e.duration <= 0) throw Error("Toast duration must be a positive number of milliseconds.");
|
|
21
|
-
let t = e.id ?? `bb-toast-${++
|
|
25
|
+
let t = e.id ?? `bb-toast-${++m}`, n = Date.now(), r = a.toasts.find((e) => e.id === t), i = e.loading ?? r?.loading ?? !1, o = e.persistent ?? i, s, c;
|
|
22
26
|
o ? (s = Infinity, c = Number.isFinite(r?.duration) ? r?.duration : r?.preLoadingDuration) : e.duration === void 0 ? r && Number.isFinite(r.duration) ? s = r.duration : r && Number.isFinite(r.preLoadingDuration) && (s = r.preLoadingDuration) : s = e.duration;
|
|
23
27
|
let l = (t) => t in e ? e[t] : r?.[t], u = {
|
|
24
28
|
id: t,
|
|
@@ -39,24 +43,24 @@ var r = 300, i = /* @__PURE__ */ new Set([
|
|
|
39
43
|
preLoadingDuration: c
|
|
40
44
|
};
|
|
41
45
|
return r ? Object.assign(r, u) : a.toasts.push(u), t;
|
|
42
|
-
},
|
|
46
|
+
}, g = (t, n) => {
|
|
43
47
|
t.removed || (t.removed = !0, e(r).then(() => {
|
|
44
48
|
a.toasts = a.toasts.filter((e) => e.id !== t.id);
|
|
45
49
|
}));
|
|
46
|
-
},
|
|
47
|
-
if (e === void 0) return a.toasts.forEach((e) =>
|
|
50
|
+
}, _ = (e, t = "manual") => {
|
|
51
|
+
if (e === void 0) return a.toasts.forEach((e) => g(e, t)), e;
|
|
48
52
|
let n = a.toasts.find((t) => t.id === e);
|
|
49
|
-
return n &&
|
|
50
|
-
},
|
|
53
|
+
return n && g(n, t), e;
|
|
54
|
+
}, v = (e, t) => a.toasts.some((t) => t.id === e) ? h({
|
|
51
55
|
...t,
|
|
52
56
|
id: e
|
|
53
|
-
}) : e,
|
|
57
|
+
}) : e, y = (e) => {
|
|
54
58
|
let t = typeof e == "string" ? { title: e } : e;
|
|
55
|
-
return typeof window > "u" ? (process.env.NODE_ENV !== "production" && console.warn("[BbToast] toast() was called during server-side rendering — ignored. Trigger toasts from client-side code (onMounted, event handlers)."), t.id ?? "") : (
|
|
56
|
-
},
|
|
57
|
-
toast:
|
|
58
|
-
dismiss:
|
|
59
|
-
update:
|
|
59
|
+
return typeof window > "u" ? (process.env.NODE_ENV !== "production" && console.warn("[BbToast] toast() was called during server-side rendering — ignored. Trigger toasts from client-side code (onMounted, event handlers)."), t.id ?? "") : (o === 0 && u(), process.env.NODE_ENV !== "production" && !t.title && !t.text && !t.portal && console.warn("[BbToast] A toast was created with no title, text, or portal — it will render empty."), process.env.NODE_ENV !== "production" && t.portal && t.actions && console.warn("[BbToast] A toast carries both `portal` and `actions` — portal content owns the body, so the actions are not rendered. Render the buttons inside the portal instead."), process.env.NODE_ENV !== "production" && t.variant && t.variant !== "default" && i.has(t.variant) && !t.icon && !t.loading && !t.portal && console.warn(`[BbToast] A "${t.variant}" toast was created with no \`icon\` — the variant tints the icon and sets announcement priority, nothing else, so this renders identically to a default toast. Pass a matching \`icon\` (e.g. lucide:circle-check / lucide:circle-x) when the tone should be visible.`), h(t));
|
|
60
|
+
}, b = (e, t) => e.position ?? t ?? n.toastPosition ?? "bottom-right", x = () => ({
|
|
61
|
+
toast: y,
|
|
62
|
+
dismiss: _,
|
|
63
|
+
update: v
|
|
60
64
|
});
|
|
61
65
|
//#endregion
|
|
62
|
-
export { l as __registerToastHost,
|
|
66
|
+
export { l as NO_HOST_WARNING_DELAY, d as __registerToastHost, y as createToast, _ as dismissToast, f as namedToastPortalRegistry, p as registerToastPortal, b as resolveToastPosition, a as toastState, v as updateToast, x as useToast };
|
|
@@ -16,13 +16,27 @@
|
|
|
16
16
|
*/
|
|
17
17
|
export declare const viewportWidth: import('vue').ShallowRef<number>, viewportHeight: import('vue').ShallowRef<number>;
|
|
18
18
|
/**
|
|
19
|
-
* The scrollbar-excluded flavor of the same singleton
|
|
20
|
-
* box
|
|
21
|
-
* claims against this basis
|
|
22
|
-
* measured claim by its width. Module-level for the same reason
|
|
23
|
-
* shared `resize` listener per flavor instead of one per
|
|
19
|
+
* The scrollbar-excluded flavor of the same singleton — the LAYOUT viewport,
|
|
20
|
+
* the box fixed-positioned elements actually reach the edges of. `useSafeArea`
|
|
21
|
+
* measures element claims against this basis: counting the scrollbar would
|
|
22
|
+
* inflate every measured claim by its width. Module-level for the same reason
|
|
23
|
+
* as above: one shared `resize` listener per flavor instead of one per
|
|
24
|
+
* component instance.
|
|
25
|
+
*
|
|
26
|
+
* Width is `documentElement.getBoundingClientRect().width`, NOT
|
|
27
|
+
* `documentElement.clientWidth` (which `useWindowSize({ includeScrollbar:
|
|
28
|
+
* false })` reads). They differ under `scrollbar-gutter: stable` — which the
|
|
29
|
+
* shipped reset sets on `<html>`: Chromium keeps reporting the full width in
|
|
30
|
+
* `clientWidth` while the reserved gutter shrinks the box every fixed element
|
|
31
|
+
* lays out in. Measured 2026-09-09 in a 414px test viewport: `innerWidth` and
|
|
32
|
+
* `clientWidth` 414, a `position: fixed; right: 0` box ending at 399, and
|
|
33
|
+
* every safe-area claim over by exactly those 15px. The root element's own
|
|
34
|
+
* border box is the one measure that tracks the real edge, and unlike
|
|
35
|
+
* `visualViewport` it does not shrink under pinch-zoom. Height stays
|
|
36
|
+
* `clientHeight`: the gutter reserves the inline axis only.
|
|
24
37
|
*/
|
|
25
|
-
export declare const viewportClientWidth: import('vue').
|
|
38
|
+
export declare const viewportClientWidth: import('vue').Ref<number, number>;
|
|
39
|
+
export declare const viewportClientHeight: import('vue').Ref<number, number>;
|
|
26
40
|
/**
|
|
27
41
|
* Re-seed every flavor from the live window, so a spec that wrote
|
|
28
42
|
* `viewportWidth.value` directly cannot leak its width into later specs.
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { ref as e } from "vue";
|
|
2
|
+
import { config as t } from "virtual:bitboss-ui/config";
|
|
3
|
+
import { useEventListener as n, useWindowSize as r } from "@vueuse/core";
|
|
3
4
|
//#region src/composables/useViewportWidth.ts
|
|
4
|
-
var { width:
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
});
|
|
5
|
+
var { width: i, height: a } = r({ initialWidth: t.ssrViewportWidth }), o = e(t.ssrViewportWidth), s = e(Infinity), c = () => {
|
|
6
|
+
typeof document > "u" || (o.value = document.documentElement.getBoundingClientRect().width, s.value = document.documentElement.clientHeight);
|
|
7
|
+
};
|
|
8
|
+
typeof window < "u" && (c(), n(window, "resize", c, { passive: !0 }));
|
|
8
9
|
//#endregion
|
|
9
|
-
export {
|
|
10
|
+
export { s as viewportClientHeight, o as viewportClientWidth, a as viewportHeight, i as viewportWidth };
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
/** Directories never descended into, matched as whole path segments. */
|
|
2
|
+
export declare const ALWAYS_SKIPPED_DIRS: ReadonlySet<string>;
|
|
3
|
+
/**
|
|
4
|
+
* 256 MiB. The cap exists only to keep database dumps and similar out of
|
|
5
|
+
* memory — a real source file is never this large, so it is never skipped.
|
|
6
|
+
*/
|
|
7
|
+
export declare const DEFAULT_MAX_FILE_SIZE: number;
|
|
8
|
+
/**
|
|
9
|
+
* From this many files up, the per-file work is spread over worker threads.
|
|
10
|
+
* Each worker brings its own libuv thread pool, so reads, hashes and regex
|
|
11
|
+
* passes run in true parallel — the difference between a cold scan that is
|
|
12
|
+
* felt and one that is not, on a laptop with a slow disk and few cores.
|
|
13
|
+
*/
|
|
14
|
+
export declare const DEFAULT_WORKER_THRESHOLD = 1500;
|
|
15
|
+
export declare const SCAN_CACHE_VERSION = 4;
|
|
16
|
+
export interface IconsScannerOptions {
|
|
17
|
+
/**
|
|
18
|
+
* Extra paths or globs scanned IN ADDITION to the project root: a vendor
|
|
19
|
+
* package that ships icon names, a directory outside the root. Relative
|
|
20
|
+
* entries resolve against the root. Additive — the root is always scanned.
|
|
21
|
+
*
|
|
22
|
+
* An entry is explicit, so the always-skip rules (`vendor`, hidden
|
|
23
|
+
* segments, `.gitignore` files ABOVE it) do not apply to the entry itself;
|
|
24
|
+
* they still apply to what lies beneath it.
|
|
25
|
+
*/
|
|
26
|
+
include?: string[];
|
|
27
|
+
/**
|
|
28
|
+
* Globs removed from the scan, on top of the built-in skips. Gitignore
|
|
29
|
+
* syntax, matched against the path relative to the root (or to the
|
|
30
|
+
* `include` entry that brought the file in).
|
|
31
|
+
*/
|
|
32
|
+
exclude?: string[];
|
|
33
|
+
/**
|
|
34
|
+
* Skip files larger than this many bytes. Only here to keep database
|
|
35
|
+
* dumps out of memory — the default is far above any source file.
|
|
36
|
+
*
|
|
37
|
+
* @defaultValue 268435456 (256 MiB)
|
|
38
|
+
*/
|
|
39
|
+
maxFileSize?: number;
|
|
40
|
+
}
|
|
41
|
+
export interface IconScannerConfig {
|
|
42
|
+
/** Absolute Vite root. */
|
|
43
|
+
root: string;
|
|
44
|
+
/** Absolute `build.outDir`; always skipped. */
|
|
45
|
+
outDir: string;
|
|
46
|
+
scanner: IconsScannerOptions;
|
|
47
|
+
/** Installed set prefixes — the only `<prefix>:` sequences looked for. */
|
|
48
|
+
prefixes: readonly string[];
|
|
49
|
+
/** Whether `prefix:name` resolves in an installed set (icons + aliases). */
|
|
50
|
+
resolves: (prefix: string, name: string) => boolean;
|
|
51
|
+
/** Where the per-file cache lives. */
|
|
52
|
+
cacheFile: string;
|
|
53
|
+
/** Everything the cached results depend on besides file content. */
|
|
54
|
+
cacheKey: string;
|
|
55
|
+
/**
|
|
56
|
+
* File count from which worker threads are used (`Infinity` = never,
|
|
57
|
+
* `0` = always). Internal knob — tests force both paths.
|
|
58
|
+
*/
|
|
59
|
+
workerThreshold?: number;
|
|
60
|
+
}
|
|
61
|
+
export interface ScanStats {
|
|
62
|
+
/** Files that passed every skip rule and were considered. */
|
|
63
|
+
files: number;
|
|
64
|
+
/** Files whose bytes were actually read. */
|
|
65
|
+
read: number;
|
|
66
|
+
/** Files whose bytes were run through the extractor (hash changed or new). */
|
|
67
|
+
extracted: number;
|
|
68
|
+
/** Files dropped for being binary or over `maxFileSize`. */
|
|
69
|
+
skipped: number;
|
|
70
|
+
/** Milliseconds, wall clock. */
|
|
71
|
+
elapsed: number;
|
|
72
|
+
/** No usable cache existed (first run, or the cache key changed). */
|
|
73
|
+
cold: boolean;
|
|
74
|
+
/** Worker threads the per-file work ran on (0 = main thread). */
|
|
75
|
+
workers: number;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* The `<prefix>:<name>` matcher for a prefix list. Longest prefix first so
|
|
79
|
+
* `mdi-light:` never loses to `mdi:`; a name is `[a-z0-9][a-z0-9-]*`, and the
|
|
80
|
+
* prefix must not be the tail of a longer word (`xlucide:eye`).
|
|
81
|
+
*/
|
|
82
|
+
export declare function iconLiteralRegExp(prefixes: readonly string[]): RegExp;
|
|
83
|
+
/**
|
|
84
|
+
* Every `prefix:name` candidate in `bytes`, deduplicated, in order of first
|
|
85
|
+
* appearance. One pass over the raw bytes (decoded 1:1 as latin1 — no UTF-8
|
|
86
|
+
* work, no parsing). A trailing dash is dropped so the static fragment of a
|
|
87
|
+
* template literal (`lucide:arrow-${dir}` → `arrow`) is still a candidate:
|
|
88
|
+
* a fragment that resolves costs one small chunk, which is acceptable.
|
|
89
|
+
*/
|
|
90
|
+
export declare function extractIconCandidates(bytes: Buffer, regex: RegExp): string[];
|
|
91
|
+
/** True when a null byte sits in the first block — the file is not text. */
|
|
92
|
+
export declare function looksBinary(bytes: Buffer): boolean;
|
|
93
|
+
/** Whether a string carries glob syntax at all. */
|
|
94
|
+
export declare const hasGlobMagic: (pattern: string) => boolean;
|
|
95
|
+
/**
|
|
96
|
+
* A small glob → RegExp for the two places the plugin matches globs against
|
|
97
|
+
* NAMES rather than gitignore paths: `iconWhitelist` entries
|
|
98
|
+
* (`tabler:calendar-*`) and the pattern half of an `include` entry. Supports
|
|
99
|
+
* `*` (no slash), `**` (anything), `?`, `[…]` classes and `{a,b}` alternation.
|
|
100
|
+
*/
|
|
101
|
+
export declare function globToRegExp(pattern: string): RegExp;
|
|
102
|
+
/** What a file scan needs to know. Plain data — it crosses the thread boundary. */
|
|
103
|
+
export interface FileScanOptions {
|
|
104
|
+
/** Set prefixes, each with its trailing colon (`lucide:`). */
|
|
105
|
+
needles: string[];
|
|
106
|
+
/** `iconLiteralRegExp(prefixes).source`. */
|
|
107
|
+
regexSource: string;
|
|
108
|
+
maxFileSize: number;
|
|
109
|
+
probeBytes: number;
|
|
110
|
+
}
|
|
111
|
+
export interface FileJob {
|
|
112
|
+
path: string;
|
|
113
|
+
/** The cached entry for this path, if any. */
|
|
114
|
+
prev: {
|
|
115
|
+
size: number;
|
|
116
|
+
mtime: number;
|
|
117
|
+
hash: string;
|
|
118
|
+
} | null;
|
|
119
|
+
}
|
|
120
|
+
export type FileScanResult =
|
|
121
|
+
/** Not a regular file, unreadable, over the cap, or binary. */
|
|
122
|
+
{
|
|
123
|
+
path: string;
|
|
124
|
+
outcome: 'skip';
|
|
125
|
+
read: boolean;
|
|
126
|
+
}
|
|
127
|
+
/** Size and mtime match the cache: bytes not read. */
|
|
128
|
+
| {
|
|
129
|
+
path: string;
|
|
130
|
+
outcome: 'fresh';
|
|
131
|
+
size: number;
|
|
132
|
+
mtime: number;
|
|
133
|
+
}
|
|
134
|
+
/** Read and hashed; the hash matches the cache, extraction skipped. */
|
|
135
|
+
| {
|
|
136
|
+
path: string;
|
|
137
|
+
outcome: 'same';
|
|
138
|
+
size: number;
|
|
139
|
+
mtime: number;
|
|
140
|
+
hash: string;
|
|
141
|
+
}
|
|
142
|
+
/** Read, hashed, extracted: raw candidates, not yet validated. */
|
|
143
|
+
| {
|
|
144
|
+
path: string;
|
|
145
|
+
outcome: 'new';
|
|
146
|
+
size: number;
|
|
147
|
+
mtime: number;
|
|
148
|
+
hash: string;
|
|
149
|
+
candidates: string[];
|
|
150
|
+
};
|
|
151
|
+
type FileInfo = {
|
|
152
|
+
isFile(): boolean;
|
|
153
|
+
size: number;
|
|
154
|
+
mtimeMs: number;
|
|
155
|
+
};
|
|
156
|
+
type FsLike = {
|
|
157
|
+
statSync: (p: string) => FileInfo;
|
|
158
|
+
fstatSync: (fd: number) => FileInfo;
|
|
159
|
+
openSync: (p: string, flags: string) => number;
|
|
160
|
+
readSync: (fd: number, buf: Buffer, offset: number, length: number, position: number) => number;
|
|
161
|
+
closeSync: (fd: number) => void;
|
|
162
|
+
};
|
|
163
|
+
type CryptoLike = {
|
|
164
|
+
hash?: (algorithm: string, data: Buffer, encoding: 'hex') => string;
|
|
165
|
+
createHash: (algorithm: string) => {
|
|
166
|
+
update: (data: Buffer) => {
|
|
167
|
+
digest: (encoding: 'hex') => string;
|
|
168
|
+
};
|
|
169
|
+
};
|
|
170
|
+
};
|
|
171
|
+
/**
|
|
172
|
+
* SYNCHRONOUS on purpose. Measured on a 10k-file project: the promise-based
|
|
173
|
+
* `readFile` costs four thread-pool round trips per file and ran at ~480 ms
|
|
174
|
+
* for the set, `openSync`+`readSync`+`closeSync` at ~190 ms. The blocking is
|
|
175
|
+
* harmless where this runs — inside a worker thread for any project large
|
|
176
|
+
* enough to notice, and for a few hundred files (or one changed file) on the
|
|
177
|
+
* main thread, where it is over before anything else could have run anyway.
|
|
178
|
+
*/
|
|
179
|
+
export declare function createFileScanner(fs: FsLike, crypto: CryptoLike, options: FileScanOptions): (job: FileJob) => FileScanResult;
|
|
180
|
+
/**
|
|
181
|
+
* How many workers a machine gets: every core but one, at least two (a
|
|
182
|
+
* dual-core laptop still gains from two threads issuing reads at once — the
|
|
183
|
+
* cold scan is disk-bound, not CPU-bound), at most four.
|
|
184
|
+
*/
|
|
185
|
+
export declare function workerCountFor(cores: number): number;
|
|
186
|
+
export declare class IconScanner {
|
|
187
|
+
private readonly cfg;
|
|
188
|
+
/** null when no set is installed — nothing can resolve, nothing is read. */
|
|
189
|
+
private readonly fileOptions;
|
|
190
|
+
private readonly scanOne;
|
|
191
|
+
private readonly workerThreshold;
|
|
192
|
+
private readonly excludes;
|
|
193
|
+
private readonly bases;
|
|
194
|
+
private readonly resolveMemo;
|
|
195
|
+
private readonly gitignoreMemo;
|
|
196
|
+
/** Absolute file path → cached result (the live cache). */
|
|
197
|
+
private entries;
|
|
198
|
+
private cold;
|
|
199
|
+
private dirty;
|
|
200
|
+
private lastWorkers;
|
|
201
|
+
constructor(cfg: IconScannerConfig);
|
|
202
|
+
/** Directories the dev server should watch besides the root. */
|
|
203
|
+
get includeDirs(): string[];
|
|
204
|
+
/** Every provider icon referenced somewhere in the scanned files. */
|
|
205
|
+
get icons(): Set<string>;
|
|
206
|
+
private includeBase;
|
|
207
|
+
private gitignoreFor;
|
|
208
|
+
/** Forget every parsed `.gitignore` — call when one changes on disk. */
|
|
209
|
+
resetGitignores(): void;
|
|
210
|
+
/**
|
|
211
|
+
* Git semantics across levels: the deepest file with a matching rule wins,
|
|
212
|
+
* a negation re-includes, and an ignored DIRECTORY is final for everything
|
|
213
|
+
* beneath it (handled by the walk pruning it).
|
|
214
|
+
*/
|
|
215
|
+
private isGitignored;
|
|
216
|
+
private isExcluded;
|
|
217
|
+
/**
|
|
218
|
+
* Whether a directory entry beneath `base` may be entered/read. `chain` is
|
|
219
|
+
* the `.gitignore` chain that applies at the entry's parent.
|
|
220
|
+
*/
|
|
221
|
+
private admits;
|
|
222
|
+
/**
|
|
223
|
+
* Whether `abs` would be picked up by a full walk — the dev watcher asks
|
|
224
|
+
* this for every changed path. Applies the same rules, segment by segment,
|
|
225
|
+
* from the base that owns the path.
|
|
226
|
+
*/
|
|
227
|
+
isCandidate(abs: string): boolean;
|
|
228
|
+
private walk;
|
|
229
|
+
/** Every file a full scan would read, absolute, deduplicated. */
|
|
230
|
+
collectFiles(): Promise<string[]>;
|
|
231
|
+
private resolvesMemo;
|
|
232
|
+
/**
|
|
233
|
+
* Fold one per-file result into a cache entry, validating fresh
|
|
234
|
+
* candidates against the installed sets. `null` entry = no file to keep.
|
|
235
|
+
*/
|
|
236
|
+
private fold;
|
|
237
|
+
/** A cache entry for a path when no set is installed: stat only. */
|
|
238
|
+
private statOnly;
|
|
239
|
+
/**
|
|
240
|
+
* Bring one file's cache entry up to date (the dev watcher path). Returns
|
|
241
|
+
* what happened so stats (and tests) can tell a skipped read from a
|
|
242
|
+
* skipped extraction.
|
|
243
|
+
*/
|
|
244
|
+
private scanFile;
|
|
245
|
+
/**
|
|
246
|
+
* Whether a scan of about `expectedFiles` files should use the worker pool.
|
|
247
|
+
*/
|
|
248
|
+
private useWorkers;
|
|
249
|
+
/**
|
|
250
|
+
* Every file's result — on the pool when there is one and the project is
|
|
251
|
+
* large enough to make its start-up worth it, else on the main thread. A
|
|
252
|
+
* worker failure of any kind degrades to the main-thread path.
|
|
253
|
+
*/
|
|
254
|
+
private scanAll;
|
|
255
|
+
private loadCache;
|
|
256
|
+
/** Full walk + scan. Reuses the on-disk cache, then persists it. */
|
|
257
|
+
scan(): Promise<ScanStats>;
|
|
258
|
+
/**
|
|
259
|
+
* Re-scan ONE file after the watcher saw it change or appear. Returns true
|
|
260
|
+
* when the union of used icons changed — the caller then invalidates the
|
|
261
|
+
* virtual module. A path the rules reject is ignored (and a stale entry for
|
|
262
|
+
* it dropped).
|
|
263
|
+
*/
|
|
264
|
+
updateFile(abs: string): Promise<boolean>;
|
|
265
|
+
/** Drop a deleted file. Returns true when the union of used icons changed. */
|
|
266
|
+
removeFile(abs: string): boolean;
|
|
267
|
+
/** Write the cache when something changed since the last write. */
|
|
268
|
+
persist(): Promise<void>;
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* The cache file: `node_modules/.cache/bitboss-ui/icon-scan.json` under the
|
|
272
|
+
* nearest `node_modules` at or above the root (Nuxt roots at `app/`, which has
|
|
273
|
+
* none of its own), falling back to the root's.
|
|
274
|
+
*/
|
|
275
|
+
export declare function iconScanCacheFile(root: string): string;
|
|
276
|
+
export {};
|