@leavepulse/ui 0.29.5 → 0.30.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 (39) hide show
  1. package/dist/chunks/LpActionBar-CxmBZpGu.js +173 -0
  2. package/dist/chunks/{LpAppShell-BJk3b-u4.js → LpAppShell-DnocEJAu.js} +1 -1
  3. package/dist/chunks/{LpCodeBlock-rS_6mO3D.js → LpCodeBlock-BWX1KZwk.js} +7 -13
  4. package/dist/chunks/LpColorPicker-CFC6iaNK.js +491 -0
  5. package/dist/chunks/{LpDisclosure-BnwP4Q-b.js → LpDisclosure-C1_YkMrd.js} +8 -2
  6. package/dist/chunks/{LpLogViewer-CVaGfTF_.js → LpLogViewer-TSRyt3t9.js} +3 -6
  7. package/dist/chunks/{LpSidebar-C_Mr-JPI.js → LpSidebar-CWSbczWi.js} +11 -2
  8. package/dist/component-names.d.ts +1 -1
  9. package/dist/components/LpActionBar.vue.d.ts +84 -0
  10. package/dist/components/LpActionBar.vue.js +4 -0
  11. package/dist/components/LpAppShell.vue.js +1 -1
  12. package/dist/components/LpCodeBlock.vue.js +1 -1
  13. package/dist/components/LpColorPicker.vue.d.ts +124 -0
  14. package/dist/components/LpColorPicker.vue.js +4 -0
  15. package/dist/components/LpDisclosure.vue.js +1 -1
  16. package/dist/components/LpLogViewer.vue.js +1 -1
  17. package/dist/components/LpNotificationBell.vue.d.ts +2 -2
  18. package/dist/components/LpSidebar.vue.d.ts +21 -0
  19. package/dist/components/LpSidebar.vue.js +1 -1
  20. package/dist/components/actionBar.d.ts +19 -0
  21. package/dist/components/actionBar.js +31 -0
  22. package/dist/components/color.d.ts +65 -0
  23. package/dist/components/color.js +158 -0
  24. package/dist/composables/useClipboard.d.ts +46 -0
  25. package/dist/composables/useClipboard.js +28 -0
  26. package/dist/index.d.ts +8 -0
  27. package/dist/index.js +145 -126
  28. package/package.json +1 -1
  29. package/src/component-names.ts +2 -0
  30. package/src/components/LpActionBar.vue +268 -0
  31. package/src/components/LpCodeBlock.vue +5 -10
  32. package/src/components/LpColorPicker.vue +784 -0
  33. package/src/components/LpDisclosure.vue +17 -2
  34. package/src/components/LpLogViewer.vue +5 -8
  35. package/src/components/LpSidebar.vue +42 -6
  36. package/src/components/actionBar.ts +73 -0
  37. package/src/components/color.ts +257 -0
  38. package/src/composables/useClipboard.ts +107 -0
  39. package/src/index.ts +21 -0
@@ -0,0 +1,173 @@
1
+ import { defineComponent, useSlots, computed, ref, watch, nextTick, openBlock, createBlock, Teleport, createVNode, Transition, withCtx, createElementBlock, normalizeStyle, normalizeClass, createElementVNode, createCommentVNode, renderSlot, toDisplayString, Fragment, renderList, createTextVNode, unref } from "vue";
2
+ import { useBarStack } from "../components/actionBar.js";
3
+ import { CLOSE_ICON } from "../components/dropdown.js";
4
+ import { _ as _sfc_main$2 } from "./LpButton-5VXXCjwF.js";
5
+ import { _ as _sfc_main$1 } from "./LpIcon-CCnX5_2j.js";
6
+ const _hoisted_1 = ["aria-label"];
7
+ const _hoisted_2 = {
8
+ key: 1,
9
+ class: "min-w-0 flex-1"
10
+ };
11
+ const _hoisted_3 = {
12
+ key: 0,
13
+ class: "truncate text-sm font-medium text-ink"
14
+ };
15
+ const _hoisted_4 = {
16
+ key: 1,
17
+ class: "truncate text-xs text-muted"
18
+ };
19
+ const _hoisted_5 = {
20
+ key: 2,
21
+ class: "flex-1"
22
+ };
23
+ const _hoisted_6 = { class: "flex shrink-0 items-center gap-2" };
24
+ const _sfc_main = /* @__PURE__ */ defineComponent({
25
+ __name: "LpActionBar",
26
+ props: {
27
+ open: { type: Boolean, default: true },
28
+ title: {},
29
+ description: {},
30
+ icon: {},
31
+ actions: { default: () => [] },
32
+ dismissible: { type: Boolean },
33
+ variant: { default: "default" },
34
+ width: { default: "contained" },
35
+ maxWidth: {},
36
+ ariaLabel: {}
37
+ },
38
+ emits: ["update:open", "dismiss"],
39
+ setup(__props, { emit: __emit }) {
40
+ const props = __props;
41
+ const emit = __emit;
42
+ const slots = useSlots();
43
+ const resolvedActions = computed(
44
+ () => props.actions.map((a, i) => ({
45
+ ...a,
46
+ variant: a.variant ?? (i === props.actions.length - 1 ? props.variant === "danger" ? "danger" : "solid" : "ghost")
47
+ }))
48
+ );
49
+ const hasBody = computed(() => !!props.title || !!props.description || !!slots.default);
50
+ const maxWidth = computed(() => props.maxWidth ?? (props.width === "full" ? "72rem" : "36rem"));
51
+ function run(action) {
52
+ if (action.disabled || action.loading) return;
53
+ void action.onClick?.();
54
+ }
55
+ function dismiss() {
56
+ emit("dismiss");
57
+ emit("update:open", false);
58
+ }
59
+ const root = ref(null);
60
+ const { register, unregister, setHeight, offset, bars } = useBarStack();
61
+ const stackOffset = computed(() => {
62
+ void bars.value;
63
+ return offset();
64
+ });
65
+ watch(
66
+ () => props.open,
67
+ async (isOpen) => {
68
+ if (!isOpen) {
69
+ unregister();
70
+ return;
71
+ }
72
+ register();
73
+ await nextTick();
74
+ if (root.value) setHeight(root.value.getBoundingClientRect().height);
75
+ },
76
+ { immediate: true }
77
+ );
78
+ return (_ctx, _cache) => {
79
+ return openBlock(), createBlock(Teleport, { to: "body" }, [
80
+ createVNode(Transition, {
81
+ "enter-active-class": "animate-[rise-in_var(--duration-medium)_var(--ease-emphasized)]",
82
+ "leave-active-class": "animate-[rise-out_var(--duration-fast)_ease]"
83
+ }, {
84
+ default: withCtx(() => [
85
+ __props.open ? (openBlock(), createElementBlock("div", {
86
+ key: 0,
87
+ ref_key: "root",
88
+ ref: root,
89
+ role: "region",
90
+ "aria-label": __props.ariaLabel ?? __props.title,
91
+ class: normalizeClass(["pointer-events-none fixed inset-x-0 bottom-0 z-(--z-modal) flex justify-center transition-[translate] duration-[var(--duration-medium)] ease-[var(--ease-emphasized)] motion-reduce:transition-none", __props.width === "full" ? "" : "p-3 sm:p-4"]),
92
+ style: normalizeStyle({ translate: `0 -${stackOffset.value}px` })
93
+ }, [
94
+ createElementVNode("div", {
95
+ class: normalizeClass(["lp-skin-panel pointer-events-auto flex items-center gap-3 border-solid bg-surface-overlay", [
96
+ // A full-width bar is the page's own furniture: square, edge to
97
+ // edge, and only its top border drawn, so it reads as a frame
98
+ // rather than as a card that happens to be very wide.
99
+ __props.width === "full" ? "w-full justify-center border-x-0 border-b-0 px-4 py-3 sm:px-6" : "w-full rounded-card px-4 py-3",
100
+ __props.variant === "danger" ? "border-danger/40" : "border-line"
101
+ ]]),
102
+ style: normalizeStyle(__props.width === "full" ? void 0 : { maxWidth: maxWidth.value })
103
+ }, [
104
+ createElementVNode("div", {
105
+ class: "flex w-full items-center gap-3",
106
+ style: normalizeStyle({ maxWidth: maxWidth.value })
107
+ }, [
108
+ __props.icon ? (openBlock(), createBlock(_sfc_main$1, {
109
+ key: 0,
110
+ name: __props.icon,
111
+ size: 18,
112
+ class: normalizeClass(["shrink-0", __props.variant === "danger" ? "text-danger" : "text-brand"])
113
+ }, null, 8, ["name", "class"])) : createCommentVNode("", true),
114
+ hasBody.value ? (openBlock(), createElementBlock("div", _hoisted_2, [
115
+ renderSlot(_ctx.$slots, "default", {}, () => [
116
+ __props.title ? (openBlock(), createElementBlock("p", _hoisted_3, toDisplayString(__props.title), 1)) : createCommentVNode("", true),
117
+ __props.description ? (openBlock(), createElementBlock("p", _hoisted_4, toDisplayString(__props.description), 1)) : createCommentVNode("", true)
118
+ ])
119
+ ])) : (openBlock(), createElementBlock("div", _hoisted_5)),
120
+ createElementVNode("div", _hoisted_6, [
121
+ renderSlot(_ctx.$slots, "actions", {}, () => [
122
+ (openBlock(true), createElementBlock(Fragment, null, renderList(resolvedActions.value, (action, i) => {
123
+ return openBlock(), createBlock(_sfc_main$2, {
124
+ key: i,
125
+ variant: action.variant,
126
+ size: "sm",
127
+ disabled: action.disabled || action.loading,
128
+ onClick: ($event) => run(action)
129
+ }, {
130
+ default: withCtx(() => [
131
+ action.loading ? (openBlock(), createBlock(_sfc_main$1, {
132
+ key: 0,
133
+ name: "lucide:loader-circle",
134
+ size: 15,
135
+ class: "animate-spin"
136
+ })) : action.icon ? (openBlock(), createBlock(_sfc_main$1, {
137
+ key: 1,
138
+ name: action.icon,
139
+ size: 15
140
+ }, null, 8, ["name"])) : createCommentVNode("", true),
141
+ createTextVNode(" " + toDisplayString(action.label), 1)
142
+ ]),
143
+ _: 2
144
+ }, 1032, ["variant", "disabled", "onClick"]);
145
+ }), 128))
146
+ ]),
147
+ __props.dismissible ? (openBlock(), createElementBlock("button", {
148
+ key: 0,
149
+ type: "button",
150
+ "aria-label": "Dismiss",
151
+ class: "group -mr-1 flex size-8 shrink-0 items-center justify-center rounded-control text-muted outline-none transition-colors duration-[var(--duration-fast)] hover:text-ink focus-visible:ring-2 focus-visible:ring-ring",
152
+ onClick: dismiss
153
+ }, [
154
+ createVNode(_sfc_main$1, {
155
+ name: "lucide:x",
156
+ size: 16,
157
+ class: normalizeClass(unref(CLOSE_ICON))
158
+ }, null, 8, ["class"])
159
+ ])) : createCommentVNode("", true)
160
+ ])
161
+ ], 4)
162
+ ], 6)
163
+ ], 14, _hoisted_1)) : createCommentVNode("", true)
164
+ ]),
165
+ _: 3
166
+ })
167
+ ]);
168
+ };
169
+ }
170
+ });
171
+ export {
172
+ _sfc_main as _
173
+ };
@@ -3,7 +3,7 @@ import { _ as _sfc_main$2 } from "./LpButton-5VXXCjwF.js";
3
3
  import { _ as _sfc_main$3 } from "./LpIcon-CCnX5_2j.js";
4
4
  import { _ as _sfc_main$5 } from "./LpScrollArea-D8xyKXcF.js";
5
5
  import { _ as _sfc_main$4 } from "./LpShift-DXNsauQZ.js";
6
- import { _ as _sfc_main$1 } from "./LpSidebar-C_Mr-JPI.js";
6
+ import { _ as _sfc_main$1 } from "./LpSidebar-CWSbczWi.js";
7
7
  const _hoisted_1 = { class: "flex h-dvh overflow-hidden bg-surface text-ink" };
8
8
  const _hoisted_2 = { class: "flex min-w-0 flex-1 flex-col" };
9
9
  const _hoisted_3 = { class: "relative flex h-16 shrink-0 items-center gap-3 border-b border-line bg-surface px-4 md:px-6" };
@@ -1,4 +1,5 @@
1
- import { defineComponent, computed, reactive, watch, ref, openBlock, createElementBlock, toDisplayString, createCommentVNode, createElementVNode, createVNode, normalizeClass, normalizeStyle, Fragment, renderList } from "vue";
1
+ import { defineComponent, computed, reactive, watch, openBlock, createElementBlock, toDisplayString, createCommentVNode, createElementVNode, createVNode, unref, normalizeClass, normalizeStyle, Fragment, renderList } from "vue";
2
+ import { useClipboard } from "../composables/useClipboard.js";
2
3
  import { tokenizeLine } from "../components/codeHighlight.js";
3
4
  import { _ as _sfc_main$1 } from "./LpIcon-CCnX5_2j.js";
4
5
  const _hoisted_1 = { class: "overflow-hidden rounded-card border border-line bg-surface font-mono text-xs" };
@@ -130,15 +131,8 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
130
131
  const showHeader = computed(
131
132
  () => Boolean(props.title || props.lang !== "plain" || props.copyable || props.lockToggle)
132
133
  );
133
- const copied = ref(false);
134
- async function copy() {
135
- try {
136
- await navigator.clipboard.writeText(copyText.value);
137
- copied.value = true;
138
- window.setTimeout(() => copied.value = false, 1400);
139
- } catch {
140
- }
141
- }
134
+ const { copied, copy: writeClipboard } = useClipboard();
135
+ const copy = () => writeClipboard(copyText.value);
142
136
  function toggleLock() {
143
137
  emit("update:locked", !props.locked);
144
138
  }
@@ -168,13 +162,13 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
168
162
  key: 1,
169
163
  type: "button",
170
164
  class: "group/copy flex items-center gap-1 rounded px-1.5 py-1 outline-none transition-colors duration-[var(--duration-fast)] hover:text-ink focus-visible:ring-2 focus-visible:ring-ring",
171
- "aria-label": copied.value ? "Copied" : "Copy code",
165
+ "aria-label": unref(copied) ? "Copied" : "Copy code",
172
166
  onClick: copy
173
167
  }, [
174
168
  createVNode(_sfc_main$1, {
175
- name: copied.value ? "lucide:check" : "lucide:copy",
169
+ name: unref(copied) ? "lucide:check" : "lucide:copy",
176
170
  size: 13,
177
- class: normalizeClass(copied.value ? "text-action" : "")
171
+ class: normalizeClass(unref(copied) ? "text-action" : "")
178
172
  }, null, 8, ["name", "class"])
179
173
  ], 8, _hoisted_7)) : createCommentVNode("", true)
180
174
  ])