@leavepulse/ui 0.30.0 → 0.31.0

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.
Files changed (38) hide show
  1. package/dist/assets/{LpTable-Bz3uJNa3.css → LpTable-Ckoi05Am.css} +8 -8
  2. package/dist/chunks/{LpActionBar-CxmBZpGu.js → LpActionBar-BlvtGB2P.js} +1 -1
  3. package/dist/chunks/{LpAddressInput-Bk6D8Bcy.js → LpAddressInput-BDkp3-Bp.js} +1 -1
  4. package/dist/chunks/{LpAppShell-DnocEJAu.js → LpAppShell-Chz8Vbtu.js} +1 -1
  5. package/dist/chunks/LpBadge-Fe0D1bYx.js +62 -0
  6. package/dist/chunks/{LpDisclosure-C1_YkMrd.js → LpDisclosure-B4kVAWfg.js} +1 -1
  7. package/dist/chunks/{LpInput-CYcTL9gj.js → LpInput-Bt4J71xn.js} +3 -2
  8. package/dist/chunks/{LpNotificationBell-CTsIcPqX.js → LpNotificationBell-gdvQY89m.js} +1 -1
  9. package/dist/chunks/{LpPasswordInput-DrYE4J5d.js → LpPasswordInput-BqMAc5HA.js} +1 -1
  10. package/dist/chunks/{LpSidebar-CWSbczWi.js → LpSidebar-BiWM_lDB.js} +64 -14
  11. package/dist/chunks/{LpSidebarNav-D6v12-36.js → LpSidebarNav-CsgeuGAu.js} +1 -1
  12. package/dist/components/LpActionBar.vue.js +1 -1
  13. package/dist/components/LpAddressInput.vue.js +1 -1
  14. package/dist/components/LpAppShell.vue.js +1 -1
  15. package/dist/components/LpBadge.vue.d.ts +13 -43
  16. package/dist/components/LpBadge.vue.js +1 -1
  17. package/dist/components/LpDisclosure.vue.js +1 -1
  18. package/dist/components/LpInput.vue.js +1 -1
  19. package/dist/components/LpNotificationBell.vue.js +1 -1
  20. package/dist/components/LpPasswordInput.vue.js +1 -1
  21. package/dist/components/LpSidebar.vue.d.ts +28 -10
  22. package/dist/components/LpSidebar.vue.js +1 -1
  23. package/dist/components/LpSidebarNav.vue.js +1 -1
  24. package/dist/components/LpTable.vue.js +47 -44
  25. package/dist/components/sidebar.d.ts +6 -0
  26. package/dist/composables/useMergedClass.d.ts +22 -0
  27. package/dist/composables/useMergedClass.js +13 -0
  28. package/dist/index.js +9 -9
  29. package/package.json +1 -1
  30. package/src/components/LpActionBar.vue +9 -1
  31. package/src/components/LpBadge.vue +32 -6
  32. package/src/components/LpDisclosure.vue +7 -1
  33. package/src/components/LpInput.vue +2 -1
  34. package/src/components/LpSidebar.vue +86 -3
  35. package/src/components/LpTable.vue +59 -39
  36. package/src/components/sidebar.ts +6 -0
  37. package/src/composables/useMergedClass.ts +56 -0
  38. package/dist/chunks/LpBadge-BPodVcJa.js +0 -45
@@ -17,6 +17,12 @@ export interface SidebarItem {
17
17
  disabled?: boolean
18
18
  /** Right-click menu for this item (e.g. "Open in new tab", "Pin"). */
19
19
  menu?: ContextMenuItemDef[]
20
+ /**
21
+ * Extra terms the sidebar's filter should match, beyond the label. For the
22
+ * item people look for under a name it does not carry — "Billing" found by
23
+ * "invoice", a page found by the feature it used to be called.
24
+ */
25
+ keywords?: string[]
20
26
  }
21
27
 
22
28
  export interface SidebarSection {
@@ -0,0 +1,56 @@
1
+ import { computed, useAttrs, type ComputedRef, type MaybeRefOrGetter, toValue } from "vue"
2
+ import { cn } from "tailwind-variants"
3
+
4
+ /*
5
+ * "The class the consumer passed should win."
6
+ *
7
+ * Tailwind emits `w-full` and `w-40` into the same layer with the same
8
+ * specificity, so which one applies comes down to their order in the stylesheet
9
+ * — not to which one the caller wrote. In practice the component's own class
10
+ * won every time: `class="w-40"` on an input that styles itself `w-full` did
11
+ * nothing, `border-r-0` could not cancel a sidebar's `border-r`, and a consumer
12
+ * had no way to tell from the outside that their class was being ignored. The
13
+ * usual workaround is to grow a prop for every class anyone might want to
14
+ * override, which is a prop per Tailwind utility and never finishes.
15
+ *
16
+ * `tailwind-variants` already ships the conflict resolution (its `cn`), and the
17
+ * kit already depends on it. This wraps it in the one shape components need:
18
+ * take the component's own classes, fold in whatever arrived through `class`,
19
+ * and let the caller's win where the two describe the same thing.
20
+ *
21
+ * Note it resolves CONFLICTS, not everything: `class="w-40"` beats `w-full`
22
+ * because both are widths, while `class="shadow-lg"` is simply added, because
23
+ * the component said nothing about shadows.
24
+ */
25
+
26
+ /**
27
+ * Merges the component's own classes with the `class` attribute the consumer
28
+ * passed, resolving Tailwind conflicts in the consumer's favour.
29
+ *
30
+ * ```ts
31
+ * const rootClass = useMergedClass(() => shell({ size: props.size }))
32
+ * ```
33
+ * ```vue
34
+ * <div :class="rootClass">
35
+ * ```
36
+ *
37
+ * Pair it with `inheritAttrs: false` (and bind the rest of `$attrs` yourself)
38
+ * so the raw `class` does not land on the element a second time, unmerged.
39
+ */
40
+ export function useMergedClass(
41
+ own: MaybeRefOrGetter<string | undefined>,
42
+ ): ComputedRef<string> {
43
+ const attrs = useAttrs()
44
+ // `cn` returns undefined when everything it was given was empty; a class
45
+ // binding is happier with "" than with undefined.
46
+ return computed(() => cn(toValue(own), attrs.class as string | undefined) ?? "")
47
+ }
48
+
49
+ /**
50
+ * The same merge as a plain function, for the places that already have both
51
+ * strings in hand and do not need the attrs lookup — a render helper, or a
52
+ * component merging a class onto a child rather than its own root.
53
+ */
54
+ export function mergeClass(...classes: (string | undefined | null | false)[]): string {
55
+ return cn(...classes) ?? ""
56
+ }
@@ -1,45 +0,0 @@
1
- import { defineComponent, computed, openBlock, createElementBlock, normalizeClass, createCommentVNode, renderSlot } from "vue";
2
- import { tv } from "tailwind-variants";
3
- const _hoisted_1 = {
4
- key: 0,
5
- class: "size-1.5 rounded-full bg-current"
6
- };
7
- const _sfc_main = /* @__PURE__ */ defineComponent({
8
- __name: "LpBadge",
9
- props: {
10
- tone: {},
11
- dot: { type: Boolean }
12
- },
13
- setup(__props) {
14
- const badge = tv({
15
- base: "inline-flex items-center gap-1.5 rounded-pill px-2.5 py-0.5 text-xs font-medium",
16
- variants: {
17
- tone: {
18
- neutral: "bg-surface-soft text-muted-strong",
19
- brand: "bg-brand-soft text-brand",
20
- action: "bg-action/15 text-action",
21
- success: "bg-action/15 text-action",
22
- // Partial trouble, which every status surface eventually needs: without
23
- // it a half-failed thing has to render as either fine or broken.
24
- warning: "bg-accent/15 text-accent",
25
- danger: "bg-danger-soft text-danger",
26
- outline: "border border-line text-ink"
27
- }
28
- },
29
- defaultVariants: { tone: "neutral" }
30
- });
31
- const props = __props;
32
- const classes = computed(() => badge({ tone: props.tone }));
33
- return (_ctx, _cache) => {
34
- return openBlock(), createElementBlock("span", {
35
- class: normalizeClass(classes.value)
36
- }, [
37
- __props.dot ? (openBlock(), createElementBlock("span", _hoisted_1)) : createCommentVNode("", true),
38
- renderSlot(_ctx.$slots, "default")
39
- ], 2);
40
- };
41
- }
42
- });
43
- export {
44
- _sfc_main as _
45
- };