@retoo/borda 0.0.2 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/borda.cjs.js +103 -23
- package/dist/borda.css +18 -8
- package/dist/borda.css.map +1 -1
- package/dist/borda.es.js +103 -23
- package/dist/borda.min.cjs.js +234 -190
- package/dist/borda.min.css +1 -1
- package/dist/borda.min.es.js +895 -851
- package/dist/borda.min.umd.js +234 -190
- package/dist/borda.umd.js +103 -23
- package/dist/index.d.ts +20 -5
- package/package.json +1 -1
package/dist/borda.umd.js
CHANGED
|
@@ -5384,6 +5384,8 @@ createHTML: (html) => {
|
|
|
5384
5384
|
BordaEvent["ON_TOUR_NEXT"] = "tour:next";
|
|
5385
5385
|
/** Fired when navigating to the previous step. */
|
|
5386
5386
|
BordaEvent["ON_TOUR_PREV"] = "tour:prev";
|
|
5387
|
+
/** Fired when a step's target fails to resolve to a DOM element, just before the tour closes. */
|
|
5388
|
+
BordaEvent["ON_TOUR_ERROR"] = "tour:error";
|
|
5387
5389
|
/** Fired when the ArrowRight key is pressed during an active tour. */
|
|
5388
5390
|
BordaEvent["ON_KEYBOARD_NEXT"] = "keyboard:next";
|
|
5389
5391
|
/** Fired when the ArrowLeft key is pressed during an active tour. */
|
|
@@ -6186,6 +6188,14 @@ createHTML: (html) => {
|
|
|
6186
6188
|
}
|
|
6187
6189
|
//#endregion
|
|
6188
6190
|
//#region src/entities/step/model/lib/resolveBordaStepTarget.ts
|
|
6191
|
+
/** Runs `querySelector`, treating a malformed selector as "no match" instead of throwing. */
|
|
6192
|
+
function queryTarget(selector) {
|
|
6193
|
+
try {
|
|
6194
|
+
return document.querySelector(selector);
|
|
6195
|
+
} catch {
|
|
6196
|
+
return null;
|
|
6197
|
+
}
|
|
6198
|
+
}
|
|
6189
6199
|
function buildSelector(query) {
|
|
6190
6200
|
const parts = [];
|
|
6191
6201
|
if (query.id) parts.push(`#${CSS.escape(query.id)}`);
|
|
@@ -6209,10 +6219,10 @@ createHTML: (html) => {
|
|
|
6209
6219
|
function resolveBordaStepTarget(target) {
|
|
6210
6220
|
if (!target) return null;
|
|
6211
6221
|
if (target instanceof HTMLElement) return target;
|
|
6212
|
-
if (typeof target === "string") return
|
|
6222
|
+
if (typeof target === "string") return queryTarget(target);
|
|
6213
6223
|
const selector = buildSelector(target);
|
|
6214
6224
|
if (!selector) return null;
|
|
6215
|
-
return
|
|
6225
|
+
return queryTarget(selector);
|
|
6216
6226
|
}
|
|
6217
6227
|
//#endregion
|
|
6218
6228
|
//#region src/app/entrypoint/modules/borda-controller/lib/useBordaController.svelte.ts
|
|
@@ -6231,6 +6241,23 @@ createHTML: (html) => {
|
|
|
6231
6241
|
const hasNextStep = /* @__PURE__ */ user_derived(() => !get(isLastStep));
|
|
6232
6242
|
const hasPrevStep = /* @__PURE__ */ user_derived(() => get(stepIndex) > 0);
|
|
6233
6243
|
const tourConfig = /* @__PURE__ */ user_derived(() => config.getConfig().tour);
|
|
6244
|
+
/**
|
|
6245
|
+
* Verifies the current step's target resolved to a DOM element.
|
|
6246
|
+
*
|
|
6247
|
+
* Emits {@link BordaEvent.ON_TOUR_ERROR} followed by {@link BordaEvent.ON_TOUR_CLOSE}
|
|
6248
|
+
* when it didn't, instead of leaving the widget rendering nothing for a step
|
|
6249
|
+
* the user can't see or dismiss.
|
|
6250
|
+
*
|
|
6251
|
+
* @returns `true` when there is no step, or its target resolved; `false` when the tour was closed due to an error.
|
|
6252
|
+
*/
|
|
6253
|
+
function checkCurrentTarget() {
|
|
6254
|
+
if (!get(step) || get(currentTarget)) return true;
|
|
6255
|
+
const error = new BordaError(`Borda: target for step ${get(currentStep)} did not resolve to an element.`);
|
|
6256
|
+
console.error(error);
|
|
6257
|
+
eventEmitter.emit(BordaEvent.ON_TOUR_ERROR, error);
|
|
6258
|
+
eventEmitter.emit(BordaEvent.ON_TOUR_CLOSE);
|
|
6259
|
+
return false;
|
|
6260
|
+
}
|
|
6234
6261
|
function apply() {
|
|
6235
6262
|
set(stepIndex, get(tourConfig)?.startStep ?? 0, true);
|
|
6236
6263
|
get(tourConfig)?.onStart?.();
|
|
@@ -6244,6 +6271,7 @@ createHTML: (html) => {
|
|
|
6244
6271
|
await entering?.prepareElement?.();
|
|
6245
6272
|
entering?.onBeforeHighlighted?.();
|
|
6246
6273
|
set(stepIndex, index, true);
|
|
6274
|
+
if (!checkCurrentTarget()) return;
|
|
6247
6275
|
entering?.onHighlighted?.();
|
|
6248
6276
|
eventEmitter.emit(BordaEvent.ON_TOUR_STEP_CHANGE, get(currentStep));
|
|
6249
6277
|
}
|
|
@@ -6335,7 +6363,8 @@ createHTML: (html) => {
|
|
|
6335
6363
|
prev,
|
|
6336
6364
|
next,
|
|
6337
6365
|
finish
|
|
6338
|
-
}
|
|
6366
|
+
},
|
|
6367
|
+
checkCurrentTarget
|
|
6339
6368
|
};
|
|
6340
6369
|
}
|
|
6341
6370
|
//#endregion
|
|
@@ -8416,11 +8445,9 @@ createHTML: (html) => {
|
|
|
8416
8445
|
const padding = /* @__PURE__ */ user_derived(getPadding);
|
|
8417
8446
|
const autoPlacement = /* @__PURE__ */ user_derived(getAutoPlacement);
|
|
8418
8447
|
const arrowSide = /* @__PURE__ */ user_derived(getArrowSide);
|
|
8419
|
-
|
|
8448
|
+
/** Reads the live target/tooltip rects and writes the resolved position into state. */
|
|
8449
|
+
function recompute() {
|
|
8420
8450
|
if (!get(target) || !get(tooltip)) return;
|
|
8421
|
-
/** Re-run on scroll so auto-flip/shift recompute against the live viewport. */
|
|
8422
|
-
scroll.x;
|
|
8423
|
-
scroll.y;
|
|
8424
8451
|
const layout = useTooltipLayout({
|
|
8425
8452
|
target: get(target),
|
|
8426
8453
|
tooltip: get(tooltip),
|
|
@@ -8439,6 +8466,19 @@ createHTML: (html) => {
|
|
|
8439
8466
|
set(left, layout.position.left, true);
|
|
8440
8467
|
set(effectivePlacement, layout.placement, true);
|
|
8441
8468
|
set(arrowOffset, layout.arrowOffset, true);
|
|
8469
|
+
}
|
|
8470
|
+
user_effect(() => {
|
|
8471
|
+
if (!get(tooltip)) return;
|
|
8472
|
+
/** Re-run when the tooltip's own size changes (e.g. an image finishes loading). */
|
|
8473
|
+
const observer = new ResizeObserver(recompute);
|
|
8474
|
+
observer.observe(get(tooltip));
|
|
8475
|
+
return () => observer.disconnect();
|
|
8476
|
+
});
|
|
8477
|
+
user_effect(() => {
|
|
8478
|
+
/** Re-run on scroll so auto-flip/shift recompute against the live viewport. */
|
|
8479
|
+
scroll.x;
|
|
8480
|
+
scroll.y;
|
|
8481
|
+
recompute();
|
|
8442
8482
|
});
|
|
8443
8483
|
return {
|
|
8444
8484
|
get top() {
|
|
@@ -8923,9 +8963,8 @@ createHTML: (html) => {
|
|
|
8923
8963
|
getDuration: () => $$props.animation.overlay.transitionDuration
|
|
8924
8964
|
});
|
|
8925
8965
|
useFocusTrap({ getContainer: () => get(bordaContainer)?.getElements()?.root ?? null });
|
|
8926
|
-
const size = /* @__PURE__ */ user_derived(() => $$props.config.size);
|
|
8927
|
-
const shape = /* @__PURE__ */ user_derived(() => $$props.config.shape);
|
|
8928
8966
|
const rootClasses = /* @__PURE__ */ user_derived(() => ["rb"]);
|
|
8967
|
+
/** Container chrome isn't per-step content, so it always tracks the live config. */
|
|
8929
8968
|
const containerProps = /* @__PURE__ */ user_derived(() => ({
|
|
8930
8969
|
...$$props.config.container,
|
|
8931
8970
|
customClasses: {
|
|
@@ -8933,13 +8972,6 @@ createHTML: (html) => {
|
|
|
8933
8972
|
root: [$$props.config.container?.customClasses?.root, containerAnimator.classes]
|
|
8934
8973
|
}
|
|
8935
8974
|
}));
|
|
8936
|
-
const tourOverlayProps = /* @__PURE__ */ user_derived(() => $$props.config.tourOverlay);
|
|
8937
|
-
const tourTooltipProps = /* @__PURE__ */ user_derived(() => $$props.config.tourTooltip);
|
|
8938
|
-
const tourImageProps = /* @__PURE__ */ user_derived(() => $$props.config.tourImage);
|
|
8939
|
-
const tourButtonsProps = /* @__PURE__ */ user_derived(() => $$props.config.tourButtons);
|
|
8940
|
-
const tourProgressProps = /* @__PURE__ */ user_derived(() => $$props.config.tourProgress);
|
|
8941
|
-
const tourSkipProps = /* @__PURE__ */ user_derived(() => $$props.config.tourSkip);
|
|
8942
|
-
const closeButtonProps = /* @__PURE__ */ user_derived(() => $$props.config.closeButton);
|
|
8943
8975
|
const tourTooltipAnimation = /* @__PURE__ */ user_derived(() => $$props.animation.isEnabled ? $$props.animation.tooltip : false);
|
|
8944
8976
|
const isAnimated = /* @__PURE__ */ user_derived(() => $$props.animation.isEnabled);
|
|
8945
8977
|
const hasGlide = /* @__PURE__ */ user_derived(() => $$props.animation.tooltip.transition === BordaTooltipTransition.GLIDE);
|
|
@@ -8947,7 +8979,22 @@ createHTML: (html) => {
|
|
|
8947
8979
|
const isStepSettling = /* @__PURE__ */ user_derived(() => $$props.scroll.isScrolling || overlayTransition.isActive);
|
|
8948
8980
|
/** In fade mode, hide the tooltip while the step settles, then fade it in at the new position. */
|
|
8949
8981
|
const isHidden = /* @__PURE__ */ user_derived(() => !get(hasGlide) && get(isAnimated) && get(isStepSettling) && !get(isShownOnScroll));
|
|
8950
|
-
|
|
8982
|
+
/** Seeded once from the initial step so the first render has content; kept in sync by the effect below. */
|
|
8983
|
+
let displayed = /* @__PURE__ */ state(proxy({
|
|
8984
|
+
step: untrack(() => $$props.controller.step),
|
|
8985
|
+
target: untrack(() => $$props.controller.currentTarget),
|
|
8986
|
+
currentStep: untrack(() => $$props.controller.currentStep),
|
|
8987
|
+
config: untrack(() => $$props.config)
|
|
8988
|
+
}));
|
|
8989
|
+
const size = /* @__PURE__ */ user_derived(() => get(displayed).config.size);
|
|
8990
|
+
const shape = /* @__PURE__ */ user_derived(() => get(displayed).config.shape);
|
|
8991
|
+
const tourOverlayProps = /* @__PURE__ */ user_derived(() => get(displayed).config.tourOverlay);
|
|
8992
|
+
const tourTooltipProps = /* @__PURE__ */ user_derived(() => get(displayed).config.tourTooltip);
|
|
8993
|
+
const tourImageProps = /* @__PURE__ */ user_derived(() => get(displayed).config.tourImage);
|
|
8994
|
+
const tourButtonsProps = /* @__PURE__ */ user_derived(() => get(displayed).config.tourButtons);
|
|
8995
|
+
const tourProgressProps = /* @__PURE__ */ user_derived(() => get(displayed).config.tourProgress);
|
|
8996
|
+
const tourSkipProps = /* @__PURE__ */ user_derived(() => get(displayed).config.tourSkip);
|
|
8997
|
+
const closeButtonProps = /* @__PURE__ */ user_derived(() => get(displayed).config.closeButton);
|
|
8951
8998
|
const tourComponents = /* @__PURE__ */ user_derived(() => {
|
|
8952
8999
|
const components = get(bordaTour)?.getComponents();
|
|
8953
9000
|
return {
|
|
@@ -8979,6 +9026,34 @@ createHTML: (html) => {
|
|
|
8979
9026
|
if ($$props.config.visibility?.isHidden) return;
|
|
8980
9027
|
$$props.scroll.scrollTo($$props.controller.currentTarget);
|
|
8981
9028
|
});
|
|
9029
|
+
user_effect(() => {
|
|
9030
|
+
if (!get(isHidden)) {
|
|
9031
|
+
set(displayed, {
|
|
9032
|
+
step: $$props.controller.step,
|
|
9033
|
+
target: $$props.controller.currentTarget,
|
|
9034
|
+
currentStep: $$props.controller.currentStep,
|
|
9035
|
+
config: $$props.config
|
|
9036
|
+
}, true);
|
|
9037
|
+
return;
|
|
9038
|
+
}
|
|
9039
|
+
/**
|
|
9040
|
+
* `step`/`currentTarget`/`currentStep`/`config` (incl. per-step overrides
|
|
9041
|
+
* like `tourProgress`) are live and swap the instant the step index
|
|
9042
|
+
* changes, so binding the tooltip/overlay to them directly would render
|
|
9043
|
+
* the new step's content immediately — visible for a frame before the
|
|
9044
|
+
* fade-out even starts. Keep showing the outgoing step's snapshot while
|
|
9045
|
+
* it fades out, and only swap once it's actually invisible.
|
|
9046
|
+
*/
|
|
9047
|
+
const timeoutId = setTimeout(() => {
|
|
9048
|
+
set(displayed, {
|
|
9049
|
+
step: $$props.controller.step,
|
|
9050
|
+
target: $$props.controller.currentTarget,
|
|
9051
|
+
currentStep: $$props.controller.currentStep,
|
|
9052
|
+
config: $$props.config
|
|
9053
|
+
}, true);
|
|
9054
|
+
}, $$props.animation.tooltip.exitDuration);
|
|
9055
|
+
return () => clearTimeout(timeoutId);
|
|
9056
|
+
});
|
|
8982
9057
|
onMount(() => {
|
|
8983
9058
|
$$props.mount();
|
|
8984
9059
|
});
|
|
@@ -8998,7 +9073,7 @@ createHTML: (html) => {
|
|
|
8998
9073
|
var consequent = ($$anchor) => {
|
|
8999
9074
|
bind_this(BordaTourOverlay($$anchor, spread_props({
|
|
9000
9075
|
get targetElement() {
|
|
9001
|
-
return
|
|
9076
|
+
return get(displayed).target;
|
|
9002
9077
|
},
|
|
9003
9078
|
get isAnimated() {
|
|
9004
9079
|
return get(isAnimated);
|
|
@@ -9012,13 +9087,13 @@ createHTML: (html) => {
|
|
|
9012
9087
|
var consequent_1 = ($$anchor) => {
|
|
9013
9088
|
bind_this(BordaTour($$anchor, {
|
|
9014
9089
|
get step() {
|
|
9015
|
-
return get(step
|
|
9090
|
+
return get(displayed).step;
|
|
9016
9091
|
},
|
|
9017
9092
|
get currentTarget() {
|
|
9018
|
-
return
|
|
9093
|
+
return get(displayed).target;
|
|
9019
9094
|
},
|
|
9020
9095
|
get currentStep() {
|
|
9021
|
-
return
|
|
9096
|
+
return get(displayed).currentStep;
|
|
9022
9097
|
},
|
|
9023
9098
|
get totalSteps() {
|
|
9024
9099
|
return $$props.controller.totalSteps;
|
|
@@ -9082,7 +9157,7 @@ createHTML: (html) => {
|
|
|
9082
9157
|
append($$anchor, fragment_1);
|
|
9083
9158
|
};
|
|
9084
9159
|
if_block(node_1, ($$render) => {
|
|
9085
|
-
if ($$props.controller.currentTarget &&
|
|
9160
|
+
if ($$props.controller.currentTarget && $$props.controller.step) $$render(consequent_2);
|
|
9086
9161
|
});
|
|
9087
9162
|
append($$anchor, fragment);
|
|
9088
9163
|
},
|
|
@@ -9213,6 +9288,11 @@ createHTML: (html) => {
|
|
|
9213
9288
|
config.getConfig().tour?.onClose?.();
|
|
9214
9289
|
await unmount$1(instance);
|
|
9215
9290
|
});
|
|
9291
|
+
eventEmitter.once(BordaEvent.ON_TOUR_ERROR, (error) => {
|
|
9292
|
+
config.getConfig().tour?.onError?.(error);
|
|
9293
|
+
});
|
|
9294
|
+
/** Validate the initial step now that ON_TOUR_ERROR/ON_TOUR_CLOSE listeners above are registered. */
|
|
9295
|
+
controller.checkCurrentTarget();
|
|
9216
9296
|
resolve(instance);
|
|
9217
9297
|
},
|
|
9218
9298
|
unmount: () => {
|
|
@@ -9255,7 +9335,7 @@ createHTML: (html) => {
|
|
|
9255
9335
|
}
|
|
9256
9336
|
return {
|
|
9257
9337
|
NAME: "@retoo/borda",
|
|
9258
|
-
VERSION: "0.
|
|
9338
|
+
VERSION: "0.1.1",
|
|
9259
9339
|
mount: mount$1,
|
|
9260
9340
|
unmount: unmount$1,
|
|
9261
9341
|
highlight: useBordaHighlight(mount$1).highlight
|
package/dist/index.d.ts
CHANGED
|
@@ -16,6 +16,8 @@ declare enum BordaEvent {
|
|
|
16
16
|
ON_TOUR_NEXT = "tour:next",
|
|
17
17
|
/** Fired when navigating to the previous step. */
|
|
18
18
|
ON_TOUR_PREV = "tour:prev",
|
|
19
|
+
/** Fired when a step's target fails to resolve to a DOM element, just before the tour closes. */
|
|
20
|
+
ON_TOUR_ERROR = "tour:error",
|
|
19
21
|
/** Fired when the ArrowRight key is pressed during an active tour. */
|
|
20
22
|
ON_KEYBOARD_NEXT = "keyboard:next",
|
|
21
23
|
/** Fired when the ArrowLeft key is pressed during an active tour. */
|
|
@@ -39,11 +41,11 @@ type BordaEventMap<T = unknown> = Map<BordaEvent, Set<BordaEventHandler<T>>>;
|
|
|
39
41
|
/** Pub/sub event bus for communication between borda components. */
|
|
40
42
|
interface BordaEventEmitter {
|
|
41
43
|
/** Subscribe a handler to an event. */
|
|
42
|
-
on(eventName: BordaEvent, handler: BordaEventHandler): void;
|
|
44
|
+
on<T = unknown>(eventName: BordaEvent, handler: BordaEventHandler<T>): void;
|
|
43
45
|
/** Subscribe a handler to an event; auto-unsubscribes after first call. */
|
|
44
|
-
once(eventName: BordaEvent, handler: BordaEventHandler): void;
|
|
46
|
+
once<T = unknown>(eventName: BordaEvent, handler: BordaEventHandler<T>): void;
|
|
45
47
|
/** Unsubscribe a specific handler from an event. */
|
|
46
|
-
off(eventName: BordaEvent, handler: BordaEventHandler): void;
|
|
48
|
+
off<T = unknown>(eventName: BordaEvent, handler: BordaEventHandler<T>): void;
|
|
47
49
|
/** Emit an event, calling all subscribed handlers with optional data. */
|
|
48
50
|
emit<T>(eventName: BordaEvent, data?: T): void;
|
|
49
51
|
/** Remove all handlers for a specific event. */
|
|
@@ -888,6 +890,8 @@ interface UseBordaControllerReturns {
|
|
|
888
890
|
apply: () => void;
|
|
889
891
|
/** Reactive public API for controlling the tour. */
|
|
890
892
|
api: BordaControllerApi;
|
|
893
|
+
/** Verifies the current step's target resolved; closes the tour and returns `false` if not. */
|
|
894
|
+
checkCurrentTarget: () => boolean;
|
|
891
895
|
}
|
|
892
896
|
|
|
893
897
|
/**
|
|
@@ -1226,6 +1230,17 @@ interface BordaTourProgressRef {
|
|
|
1226
1230
|
getElements: () => BordaTourProgressElements;
|
|
1227
1231
|
}
|
|
1228
1232
|
|
|
1233
|
+
/**
|
|
1234
|
+
* Base error class for all borda runtime errors.
|
|
1235
|
+
*
|
|
1236
|
+
* Using a named subclass makes borda errors easy to identify
|
|
1237
|
+
* in stack traces and `instanceof` checks.
|
|
1238
|
+
*/
|
|
1239
|
+
declare class BordaError extends Error {
|
|
1240
|
+
readonly name = "BordaError";
|
|
1241
|
+
constructor(message: string);
|
|
1242
|
+
}
|
|
1243
|
+
|
|
1229
1244
|
/** Props for the BordaTour step composition component. */
|
|
1230
1245
|
interface BordaTourProps {
|
|
1231
1246
|
step: BordaStep;
|
|
@@ -1235,9 +1250,7 @@ interface BordaTourProps {
|
|
|
1235
1250
|
size: ComponentSize;
|
|
1236
1251
|
shape: ComponentShape;
|
|
1237
1252
|
isSkipChecked: boolean;
|
|
1238
|
-
/** Hides the tooltip (fade transition) while scrolling/transitioning between steps. */
|
|
1239
1253
|
isHidden: boolean;
|
|
1240
|
-
/** Enables position gliding of the tooltip between steps (glide transition). */
|
|
1241
1254
|
hasGlide: boolean;
|
|
1242
1255
|
tourTooltipAnimation: BordaTourTooltipAnimation | false;
|
|
1243
1256
|
tourTooltipProps: Partial<BordaTourTooltipProps>;
|
|
@@ -1280,6 +1293,8 @@ interface BordaTourConfig {
|
|
|
1280
1293
|
onFinish: () => void;
|
|
1281
1294
|
/** Called when the tour is dismissed before completion (close button, backdrop or Escape), before the unmount animation. */
|
|
1282
1295
|
onClose: () => void;
|
|
1296
|
+
/** Called when a step's target fails to resolve to a DOM element, just before the tour closes. */
|
|
1297
|
+
onError: (error: BordaError) => void;
|
|
1283
1298
|
/**
|
|
1284
1299
|
* Enable keyboard navigation: ArrowRight/ArrowLeft for next/prev, Escape to close.
|
|
1285
1300
|
* Defaults to `true`. Set to `false` to disable all keyboard handling.
|