@stsdti/approvable-vue 0.1.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.
- package/LICENSE +21 -0
- package/README.md +108 -0
- package/dist/approvable-vue.mjs +902 -0
- package/dist/approvable-vue.mjs.map +1 -0
- package/package.json +58 -0
- package/src/components/approvable/Approvable.vue +197 -0
- package/src/components/approvable/ApprovableAuditTimeline.vue +253 -0
- package/src/components/approvable/ApprovableButtons.vue +80 -0
- package/src/components/approvable/ApprovableStep.vue +235 -0
- package/src/components/approvable/ApprovableStepComment.vue +155 -0
- package/src/components/approvable/ApproveStatusInfo.vue +33 -0
- package/src/components/approvable/action-renderers.js +23 -0
- package/src/components/select/approvable-status-select/ApprovableStatusSelect.vue +64 -0
- package/src/components/select/approvable-status-select/ApprovableStatusSelectOption.vue +16 -0
- package/src/config.js +26 -0
- package/src/icons.js +36 -0
- package/src/index.js +109 -0
- package/src/messages.js +19 -0
- package/src/themes/approvable.css +1171 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"approvable-vue.mjs","sources":["../src/messages.js","../src/components/approvable/ApprovableAuditTimeline.vue","../src/components/approvable/ApprovableStepComment.vue","../src/components/approvable/action-renderers.js","../src/config.js","../src/icons.js","../src/components/approvable/ApprovableStep.vue","../src/components/approvable/ApproveStatusInfo.vue","../src/components/approvable/Approvable.vue","../src/components/approvable/ApprovableButtons.vue","../src/components/select/approvable-status-select/ApprovableStatusSelect.vue","../src/components/select/approvable-status-select/ApprovableStatusSelectOption.vue","../src/index.js"],"sourcesContent":["import { inject } from 'vue'\nimport { DEFAULT_MESSAGES, mergeMessages } from '@stsdti/approvable-core'\n\nexport const APPROVABLE_MESSAGES = Symbol('approvable.messages')\n\n/**\n * The user-facing strings, in English.\n *\n * Defined in core so that every binding ships the same wording and the same\n * override surface — a string added for the React components is available\n * here too. Any of it can be replaced:\n *\n * app.use(Approvable, { messages: { comments: 'Comentarii' } })\n */\nexport function useMessages () {\n return mergeMessages(inject(APPROVABLE_MESSAGES, null))\n}\n\nexport { DEFAULT_MESSAGES, mergeMessages }\n","<script setup>\nimport { computed, ref, watch } from 'vue'\nimport { ApprovableAuditRepository, formatMessage } from '@stsdti/approvable-core'\nimport { useMessages } from '../../messages.js'\n\nconst props = defineProps({\n approvableId: { type: [Number, String], required: true },\n limit: { type: Number, default: 100 },\n showHeader: { type: Boolean, default: true }\n})\n\nconst emits = defineEmits(['loaded'])\n\nconst messages = useMessages()\nconst repository = new ApprovableAuditRepository()\nconst audits = ref([])\nconst loading = ref(false)\nconst error = ref('')\n\n// Only the fields a reader actually cares about. Everything else (ids,\n// timestamps we already show, internal bookkeeping) is intentionally hidden.\nconst FIELD_LABELS = {\n approvable_status_name: 'Status',\n comment: 'Comment',\n responsible: 'Assigned to',\n is_active: 'Active step'\n}\n\n// One glyph per kind of event, keyed by the `kind` we resolve below. Drawn on\n// the same 16-unit grid and at the same weight as the discs on the approval\n// trail, so a history row and a step row read as the same object.\nconst ICONS = {\n approve: { paths: ['M4 8.4l2.8 2.8 5.4-6'], width: 2.8 },\n reject: { paths: ['M5.2 5.2l5.6 5.6M10.8 5.2l-5.6 5.6'], width: 2.4 },\n comment: { paths: ['M8 4.6v3.6l2.6 1.6'], width: 2.2 },\n status: { paths: ['M4 8h8M9.2 5.4L11.8 8l-2.6 2.6'], width: 2.2 },\n undo: { paths: ['M4.4 6.6h3.4M4.4 6.6v-3M4.6 9.4a3.6 3.6 0 1 0 1-3.2'], width: 2 },\n signal: { paths: ['M8 3.4v3.2M5.2 5.2l2.2 2.2M8 11.6a1.4 1.4 0 1 0 0-2.8 1.4 1.4 0 0 0 0 2.8'], width: 1.8 },\n created: { paths: ['M4.4 8h7.2'], width: 2.2 },\n update: { paths: ['M4.4 8h7.2'], width: 2.2 }\n}\n\n/** Bookkeeping, not news: these rows are dimmed the way the design dims them. */\nconst QUIET_KINDS = new Set(['created', 'update'])\n\nconst groups = computed(() => {\n // The workflow-level rows are noise for a reader, so keep only step changes.\n const stepAudits = audits.value.filter(audit => audit.approvable_step_id)\n const grouped = new Map()\n for (const audit of stepAudits) {\n const key = audit.request_id || `audit-${audit.id}`\n if (!grouped.has(key)) grouped.set(key, [])\n grouped.get(key).push(audit)\n }\n return [...grouped.values()].map(entries => {\n const audit = entries[0]\n // Resolved here rather than in the template, where it was called twice per\n // row on every render — once for the marker class and once for its icon.\n const kind = auditKind(audit)\n // A row only needs a second line when there is something to put on it.\n const details = entries.flatMap(changeRows)\n\n return {\n id: audit.request_id || `audit-${audit.id}`,\n entries,\n audit,\n kind,\n // A modifier class rather than utilities: the accent for each kind of\n // event is a theme decision, so it belongs in the stylesheets alongside\n // every other colour, not baked into the component.\n kindClass: `approvable-timeline-marker--${kind}`,\n icon: ICONS[kind],\n isQuiet: QUIET_KINDS.has(kind),\n isSingleLine: details.length === 0\n }\n })\n // Newest first: the last thing that happened is the thing a reader opened\n // the history for.\n .sort((a, b) => new Date(b.audit.created_at) - new Date(a.audit.created_at))\n})\n\nfunction auditKind (audit) {\n const button = audit.metadata?.button\n if (button?.is_undo) return 'undo'\n if (button?.result === 'rejected') return 'reject'\n if (button?.result === 'approved') return 'approve'\n if (audit.metadata?.operation === 'comment') return 'comment'\n if (audit.metadata?.operation === 'signal') return 'signal'\n if (audit.event === 'created') return 'created'\n if (statusChanged(audit)) return 'status'\n return 'update'\n}\n\nfunction statusChanged (audit) {\n const before = audit.old_values?.approvable_status_name\n const after = audit.new_values?.approvable_status_name\n return after !== undefined && before !== after\n}\n\nfunction operationTitle (audit) {\n const button = audit.metadata?.button\n if (button) {\n const label = button.text || button.label || button.id || 'action'\n if (button.is_undo) return 'Reverted the decision'\n if (button.is_revision) return `Changed decision to ${label}`\n return label\n }\n if (audit.metadata?.operation === 'comment') return 'Comment added'\n if (audit.metadata?.operation === 'signal') return `Signal received: ${audit.metadata?.signal?.name || ''}`.trim()\n if (audit.event === 'created') return 'Step started'\n const after = audit.new_values?.approvable_status_name\n if (statusChanged(audit) && after) return `Status set to ${after}`\n return 'Step updated'\n}\n\nfunction actorLabel (actor = {}) {\n if (actor.type === 'system') return 'System'\n if (actor.name) return actor.name\n if (actor.email) return actor.email\n if (actor.id) return actor.type === 'fake' ? `Test user ${actor.id}` : `User ${actor.id}`\n if (actor.type === 'fake') return 'Test identity'\n return 'Automated'\n}\n\n// Changed fields worth surfacing, with the status change collapsed into a\n// single \"before → after\" row (never the raw id).\nfunction changeRows (entry) {\n const oldValues = entry.old_values || {}\n const newValues = entry.new_values || {}\n return Object.keys(FIELD_LABELS)\n .filter(key => key in oldValues || key in newValues)\n .map(key => ({ key, label: FIELD_LABELS[key], oldValue: oldValues[key], newValue: newValues[key] }))\n .filter(row => row.oldValue !== row.newValue)\n}\n\n/** A change only reads as \"before → after\" when there was a before. */\nfunction hasPreviousValue (change) {\n return change.oldValue !== undefined && change.oldValue !== null && change.oldValue !== ''\n}\n\nfunction displayValue (value) {\n if (value === null || value === undefined || value === '') return '—'\n if (typeof value === 'boolean') return value ? 'Yes' : 'No'\n if (Array.isArray(value)) return value.length ? value.join(', ') : '—'\n const text = typeof value === 'object' ? JSON.stringify(value) : String(value)\n return text.length > 180 ? `${text.slice(0, 177)}…` : text\n}\n\nfunction formatDate (value) {\n if (!value) return ''\n const date = new Date(value)\n return Number.isNaN(date.getTime()) ? value : new Intl.DateTimeFormat(undefined, {\n dateStyle: 'medium',\n timeStyle: 'short'\n }).format(date)\n}\n\nasync function refresh () {\n if (!props.approvableId) {\n audits.value = []\n loading.value = false\n error.value = 'The approval history is unavailable because the approvable has no id.'\n return\n }\n\n loading.value = true\n error.value = ''\n try {\n const response = await repository.fetchTimeline(props.approvableId, props.limit)\n if (!response || response.status < 200 || response.status >= 300) {\n throw new Error(response?.data?.message || 'The audit timeline could not be loaded.')\n }\n const data = Array.isArray(response.data) ? response.data : response.data?.data\n audits.value = Array.isArray(data) ? data : []\n } catch (exception) {\n error.value = exception?.message || 'The audit timeline could not be loaded.'\n } finally {\n loading.value = false\n }\n}\n\nconst eventSummary = computed(() => formatMessage(messages.eventCount, { count: groups.value.length }))\n\n// The dialog titles itself with the count, and only this component knows it.\nwatch(groups, (value) => emits('loaded', value.length))\n\nwatch(() => props.approvableId, refresh, { immediate: true })\ndefineExpose({ refresh })\n</script>\n\n<template>\n <section :class=\"['approvable-timeline', showHeader && 'approvable-timeline--panel']\">\n <div v-if=\"showHeader\" class=\"approvable-timeline-header\">\n <p class=\"approvable-timeline-eyebrow\">{{ messages.history }}</p>\n <h3 class=\"approvable-timeline-title\">{{ eventSummary }}</h3>\n <button type=\"button\" class=\"approvable-timeline-refresh\" :disabled=\"loading\" @click=\"refresh\">\n {{ loading ? 'Loading…' : 'Refresh' }}\n </button>\n </div>\n\n <div v-if=\"loading\" class=\"approvable-timeline-state\" role=\"status\">\n <span class=\"approvable-spinner\" aria-hidden=\"true\" />\n Loading approval history…\n </div>\n <p v-else-if=\"error\" class=\"approvable-timeline-error\">{{ error }}</p>\n <p v-else-if=\"!groups.length\" class=\"approvable-timeline-state\">No approval activity yet.</p>\n\n <template v-else>\n <ol class=\"approvable-timeline-list\">\n <li\n v-for=\"group in groups\"\n :key=\"group.id\"\n :class=\"['approvable-timeline-item', {\n 'approvable-timeline-item--single-line': group.isSingleLine,\n 'approvable-timeline-item--quiet': group.isQuiet\n }]\"\n >\n <span :class=\"['approvable-timeline-marker', group.kindClass]\">\n <svg fill=\"none\" stroke=\"currentColor\" :stroke-width=\"group.icon.width\" stroke-linecap=\"round\" stroke-linejoin=\"round\" viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path v-for=\"(d, i) in group.icon.paths\" :key=\"i\" :d=\"d\" />\n </svg>\n </span>\n\n <div class=\"approvable-timeline-content\">\n <div class=\"approvable-timeline-line\">\n <p class=\"approvable-timeline-actor\">{{ actorLabel(group.audit.actor) }}</p>\n <p class=\"approvable-timeline-operation\">{{ operationTitle(group.audit) }}</p>\n <time class=\"approvable-timeline-time\">{{ formatDate(group.audit.created_at) }}</time>\n </div>\n\n <template v-for=\"entry in group.entries\" :key=\"entry.id\">\n <template v-for=\"change in changeRows(entry)\" :key=\"`${entry.id}-${change.key}`\">\n <p v-if=\"change.key === 'comment'\" class=\"approvable-timeline-comment\">\n {{ displayValue(change.newValue) }}\n </p>\n <p v-else class=\"approvable-timeline-change\">\n <span class=\"approvable-timeline-change-label\">{{ change.label }}</span>\n <template v-if=\"hasPreviousValue(change)\">\n <span class=\"approvable-timeline-value approvable-timeline-value--old\">{{ displayValue(change.oldValue) }}</span>\n <span class=\"approvable-timeline-arrow\">→</span>\n </template>\n <span class=\"approvable-timeline-value approvable-timeline-value--new\">{{ displayValue(change.newValue) }}</span>\n </p>\n </template>\n </template>\n </div>\n </li>\n </ol>\n\n <p class=\"approvable-timeline-footer\">{{ messages.allEventsShown }}</p>\n </template>\n </section>\n</template>\n","<template>\n <div ref=\"rootRef\" class=\"approvable-popover\">\n <button class=\"approvable-btn\" :title=\"messages.comments\" type=\"button\" @click=\"onToggle\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.8\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M8 9h8\" />\n <path d=\"M8 13h6\" />\n <path d=\"M18 4a3 3 0 0 1 3 3v8a3 3 0 0 1 -3 3h-5l-5 3v-3h-2a3 3 0 0 1 -3 -3v-8a3 3 0 0 1 3 -3h12z\" />\n </svg>\n </button>\n\n <div v-if=\"isOpen\" class=\"approvable-popover-panel\">\n <div v-if=\"isLoading\" class=\"approvable-loading\">\n <span class=\"approvable-spinner\" />\n </div>\n\n <div class=\"approvable-popover-title\">{{ messages.comments }}</div>\n\n <div v-if=\"commentedBy\" class=\"approvable-popover-meta\">\n <div>{{ messages.commentAuthor }}:</div>\n <div class=\"approvable-popover-author\">{{ commentedBy }}</div>\n </div>\n\n <template v-if=\"!disabled\">\n <textarea\n ref=\"textareaRef\"\n v-model=\"comment\"\n class=\"approvable-textarea\"\n rows=\"1\"\n @input=\"resizeTextarea\"\n />\n\n <div class=\"approvable-popover-actions\">\n <button class=\"approvable-btn approvable-btn--primary\" type=\"button\" @click=\"onComment\">\n {{ messages.save }}\n </button>\n </div>\n </template>\n </div>\n </div>\n</template>\n\n<script setup>\nimport { computed, nextTick, onBeforeUnmount, onMounted, ref, useTemplateRef } from 'vue'\n\nimport { ApprovableStepRepository, get, isSuccessResponse, notifyError, notifySuccess } from '@stsdti/approvable-core'\nimport { useMessages } from '../../messages.js'\n\nconst props = defineProps({\n approvableStep: {\n required: true,\n },\n disabled: {\n required: true,\n type: Boolean,\n },\n})\n\nconst emits = defineEmits(['isLoading', 'refresh'])\n\nconst rootRef = useTemplateRef('rootRef')\nconst textareaRef = useTemplateRef('textareaRef')\n\nconst isOpen = ref(false)\nconst isLoading = ref(false)\nconst comment = ref(null)\n\nconst commentedBy = computed(() => {\n return get(props.approvableStep, 'commented_by')\n})\n\nfunction onToggle () {\n isOpen.value ? hide() : show()\n}\n\nfunction show () {\n comment.value = get(props.approvableStep, 'comment')\n isOpen.value = true\n nextTick(resizeTextarea)\n}\n\nfunction hide () {\n isOpen.value = false\n}\n\nfunction resizeTextarea () {\n const textarea = textareaRef.value\n if (!textarea) {\n return\n }\n textarea.style.height = 'auto'\n textarea.style.height = `${textarea.scrollHeight}px`\n}\n\nfunction onDocumentClick (event) {\n if (isOpen.value && rootRef.value && !rootRef.value.contains(event.target)) {\n hide()\n }\n}\n\nfunction onDocumentKeydown (event) {\n if (event.key === 'Escape') {\n hide()\n }\n}\n\nonMounted(() => {\n document.addEventListener('click', onDocumentClick)\n document.addEventListener('keydown', onDocumentKeydown)\n})\n\nonBeforeUnmount(() => {\n document.removeEventListener('click', onDocumentClick)\n document.removeEventListener('keydown', onDocumentKeydown)\n})\n\nconst messages = useMessages()\n\nasync function onComment () {\n if (!get(props.approvableStep, 'comment') && !comment.value) {\n notifyError(messages.commentRequired)\n return\n }\n\n isLoading.value = true\n emits('isLoading', true)\n\n const data = {\n comment: comment.value,\n }\n\n const response = await new ApprovableStepRepository().comment(props.approvableStep.id, data)\n\n if (isSuccessResponse(response)) {\n notifySuccess(messages.commentSaved)\n hide()\n emits('refresh')\n } else {\n notifyError(messages.commentFailed)\n }\n\n isLoading.value = false\n emits('isLoading', false)\n}\n</script>\n","import { markRaw } from 'vue'\nimport {\n registerActionRenderer,\n unregisterActionRenderer,\n actionRenderer,\n actionSlotName\n} from '@stsdti/approvable-core'\n\n/**\n * Vue binding over the core action registry.\n *\n * The only thing Vue-specific about registering a renderer is that a component\n * must be marked raw before it goes into reactive state, so that is all this\n * layer adds. The registry itself is framework-free, which is what allows a\n * React binding to reuse it without inheriting Vue's reactivity rules.\n */\nexport function registerApprovableActionRenderer (name, component) {\n return registerActionRenderer(name, markRaw(component))\n}\n\nexport { unregisterActionRenderer as unregisterApprovableActionRenderer }\nexport { actionRenderer as approvableActionRenderer }\nexport { actionSlotName as approvableActionSlotName }\n","import { inject } from 'vue'\n\nexport const APPROVABLE_LINK_COMPONENT = Symbol('approvable.linkComponent')\n\n/**\n * Which component renders a button that navigates.\n *\n * Defaults to a plain anchor so the package works with no router installed.\n * Hardcoding <router-link> instead would silently fail to resolve — and log a\n * Vue warning — in any application without vue-router.\n *\n * Applications using a router opt in once, at install:\n *\n * app.use(Approvable, { linkComponent: RouterLink })\n */\nexport function useLinkComponent () {\n return inject(APPROVABLE_LINK_COMPONENT, 'a')\n}\n\n/**\n * Anchors take `href`; RouterLink and NuxtLink take `to`. Binding the right one\n * keeps the call sites free of that distinction.\n */\nexport function linkProps (component, target) {\n return component === 'a' ? { href: target } : { to: target }\n}\n","import { inject } from 'vue'\nimport { isClassIcon, isRegisteredIcon, isUrlIcon } from '@stsdti/approvable-core'\n\nexport const APPROVABLE_ICON_REGISTRY = Symbol('approvable.iconRegistry')\n\n/**\n * How a button's `icon` is rendered.\n *\n * An icon is a *name*, resolved against a registry the application supplies —\n * never raw markup rendered with v-html. A button's icon comes from the\n * workflow definition — authored in the editor, stored, and then displayed in\n * the browser of every person who can see the approval — so v-html here would\n * let whoever can edit a workflow run script in every approver's session.\n * `<svg onload=\"...\">` is enough; it would be a stored XSS with an unusually\n * good distribution list.\n *\n * app.use(Approvable, {\n * icons: { approve: CheckIcon, reject: XIcon }\n * })\n *\n * Anything not in the registry falls back to the two safe forms: an `http(s)`\n * URL rendered as <img>, or a CSS class rendered on an <i>.\n * A `#icon` slot is available for full control.\n *\n * Applications that genuinely need bespoke SVG register a component for it,\n * which puts the markup in application code — where it is reviewed — rather\n * than in a database row.\n */\nexport function useIconRegistry () {\n return inject(APPROVABLE_ICON_REGISTRY, {})\n}\n\n// The three predicates come from core rather than being defined here: the\n// React binding applies the same rules, and a rule about what is safe to render\n// is only worth trusting while there is one copy of it.\nexport { isRegisteredIcon, isUrlIcon, isClassIcon }\n","<template>\n <li v-if=\"step.isVisible\" :class=\"rowClass\">\n <span :class=\"discClass\">\n <svg\n v-if=\"discGlyph\"\n aria-hidden=\"true\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n viewBox=\"0 0 16 16\"\n >\n <path :d=\"discGlyph.d\" :stroke-width=\"discGlyph.width\" />\n </svg>\n </span>\n\n <div class=\"approvable-step-body\">\n <div class=\"approvable-step-line\">\n <slot :step=\"value\" name=\"approvableStepInfo\">\n <span class=\"approvable-step-name\">{{ step.approverName }}</span>\n </slot>\n\n <slot :step=\"value\" :role=\"step.approverRole\" name=\"approvableStepRole\">\n <!-- The title is the whole role, so a clipped one is still readable\n on hover; without a role the spacer keeps the row's geometry. -->\n <span v-if=\"step.approverRole\" :title=\"step.approverRole\" class=\"approvable-step-role\">\n {{ step.approverRole }}\n </span>\n <span v-else class=\"approvable-step-spacer\" />\n </slot>\n\n <!-- On the step being waited on the buttons carry the meaning, so the\n status word is redundant; everywhere else it is the outcome. -->\n <span v-if=\"showStatus\" class=\"approvable-step-status\">\n <span v-if=\"step.statusName\">{{ step.statusName }}</span>\n <time v-if=\"step.performedAt\" class=\"approvable-step-date\">{{ step.performedAt }}</time>\n </span>\n\n <div v-if=\"hasActions\" class=\"approvable-step-actions\">\n <div class=\"approvable-btn-group\">\n <!-- APPROVABLE BUTTONS (custom renderer per button, else basic) -->\n <template v-for=\"(button, index) in step.buttons\" :key=\"button.id ?? index\">\n <component\n :is=\"buttonRenderer(button)\"\n v-if=\"buttonRenderer(button)\"\n :action-ui=\"button.action_ui\"\n :approvable=\"approvable\"\n :button=\"button\"\n :buttons=\"[button]\"\n :complete=\"onApproveStatusChange\"\n :resource=\"resource\"\n :step=\"value\"\n @is-loading=\"(isLoading) => emits('isLoading', isLoading)\"\n @refresh=\"emits('refresh')\"\n />\n <component\n :is=\"linkComponent\"\n v-else-if=\"button.link\"\n v-bind=\"linkProps(linkComponent, button.link)\"\n >\n <button\n :title=\"button.tooltip\"\n :class=\"buttonClass(button)\"\n type=\"button\"\n @click=\"onApproveStatusChange(button)\"\n >\n <i v-if=\"isClassIcon(button.icon)\" :class=\"button.icon\"></i>\n </button>\n </component>\n <button\n v-else\n :title=\"button.tooltip\"\n :class=\"buttonClass(button)\"\n type=\"button\"\n @click=\"onApproveStatusChange(button)\"\n >\n <i v-if=\"isClassIcon(button.icon)\" :class=\"button.icon\"></i>\n {{ button.text }}\n </button>\n </template>\n </div>\n\n <div v-if=\"value.can_comment\" class=\"approvable-btn-group\">\n <approvable-step-comment\n :approvable-step=\"value\"\n :disabled=\"!value.can_comment\"\n @refresh=\"emits('refresh')\"\n @is-loading=\"(isLoading) => emits('isLoading', isLoading)\"\n />\n </div>\n </div>\n </div>\n\n <p v-if=\"step.comment.text\" class=\"approvable-step-comment\">\n <span :title=\"step.comment.title\">{{ commentText }}</span>\n <button\n v-if=\"step.comment.isTrimmed\"\n type=\"button\"\n class=\"approvable-step-comment-more\"\n :aria-expanded=\"isCommentExpanded\"\n @click=\"isCommentExpanded = !isCommentExpanded\"\n >\n {{ isCommentExpanded ? messages.showLess : messages.showMore }}\n </button>\n </p>\n </div>\n </li>\n</template>\n\n<script setup>\nimport { computed, ref } from 'vue'\nimport {\n approvableStatusTone,\n approvableStepGlyph,\n createStepViewModel,\n performStepAction\n} from '@stsdti/approvable-core'\nimport ApprovableStepComment from './ApprovableStepComment.vue'\nimport { approvableActionRenderer } from './action-renderers.js'\nimport { linkProps, useLinkComponent } from '../../config.js'\nimport { isClassIcon } from '../../icons.js'\nimport { useMessages } from '../../messages.js'\n\nconst emits = defineEmits(['isLoading', 'refresh'])\n\nconst props = defineProps({\n value: {\n type: Object,\n required: true\n },\n approvable: {\n type: Object,\n required: true\n },\n resource: {\n type: Object,\n required: true\n }\n})\n\nconst linkComponent = useLinkComponent()\nconst messages = useMessages()\n\nconst isCommentExpanded = ref(false)\n\n// Every derivation lives in core, so this component is left with rendering and\n// event plumbing only — and a React binding computes exactly the same values.\nconst step = computed(() => createStepViewModel(props.value))\n\nconst tone = computed(() => approvableStatusTone(step.value.status))\n\n/**\n * A row shows controls when it has any — a finished step usually has none, and\n * shows when it was decided instead.\n */\nconst hasActions = computed(() => step.value.buttons.length > 0 || !!props.value.can_comment)\n\nconst showStatus = computed(() => (\n (!step.value.isActive || !hasActions.value) && !!(step.value.statusName || step.value.performedAt)\n))\n\nconst rowClass = computed(() => ({\n 'approvable-step': true,\n 'approvable-step--active': step.value.isActive,\n // A step nobody has reached yet is dimmed; one with an outcome is not.\n 'approvable-step--pending': !step.value.isActive && !tone.value,\n [`approvable-step--${tone.value}`]: !!tone.value,\n // Nothing wraps below the name, so the row can hold to a single line.\n 'approvable-step--single-line': !hasActions.value && !step.value.comment.text\n}))\n\n/** `ring` and `pending` are drawn by the disc's border alone — no path. */\nconst GLYPHS = {\n check: { d: 'M4 8.4l2.8 2.8 5.4-6', width: 2.8 },\n cross: { d: 'M5.2 5.2l5.6 5.6M10.8 5.2l-5.6 5.6', width: 2.4 },\n dash: { d: 'M4.4 8h7.2', width: 2.2 }\n}\n\n/** The disc's own modifier: the glyph names the shape, the tone names the colour. */\nconst DISC_MODIFIERS = {\n check: 'success',\n cross: 'danger',\n dash: 'muted',\n ring: 'ring',\n pending: 'pending'\n}\n\nconst glyph = computed(() => approvableStepGlyph(tone.value, step.value.isActive))\n\nconst discGlyph = computed(() => GLYPHS[glyph.value] ?? null)\n\nconst discClass = computed(() => ({\n 'approvable-step-disc': true,\n [`approvable-step-disc--${DISC_MODIFIERS[glyph.value]}`]: true\n}))\n\nconst commentText = computed(() => (\n isCommentExpanded.value ? step.value.comment.text : step.value.comment.preview\n))\n\nconst buttonClass = (button) => ({\n 'approvable-btn': true,\n // A button carrying only an icon collapses to a circle, so the row keeps its\n // rhythm instead of stretching around an empty label.\n 'approvable-btn--icon': !button.text,\n 'approvable-btn--primary': button.result === 'approved'\n})\n\nconst buttonRenderer = (button) => {\n if (!step.value.isActive) {\n return null\n }\n\n return approvableActionRenderer(button?.action_ui)\n}\n\nconst onApproveStatusChange = async (buttonOrId) => {\n emits('isLoading', true)\n\n const result = await performStepAction({\n stepId: step.value.id,\n button: buttonOrId,\n buttons: step.value.buttons\n })\n\n emits('isLoading', false)\n\n // Refresh after any attempted request, success or failure — a failed action\n // still means the local state may be stale. Only a skipped one (no id, no\n // button, or a presentational button) reloads nothing, since it sent nothing.\n if (!result.skipped) {\n emits('refresh')\n }\n}\n</script>\n","<template>\n <span :class=\"badgeClass\">{{ badgeName }}</span>\n</template>\n\n<script setup>\nimport { computed } from 'vue'\nimport { ApprovableStatus, get } from '@stsdti/approvable-core'\n\nconst props = defineProps({\n value: {\n required: true\n },\n label: {\n default: null\n }\n})\nconst badgeClass = computed(() => {\n const approvableStatusCode = get(props.value, 'code', ' - ')\n return {\n 'approvable-badge': true,\n 'approvable-badge--draft': [ApprovableStatus.CODES.CODE_DRAFT].includes(approvableStatusCode),\n 'approvable-badge--waiting': [ApprovableStatus.CODES.CODE_WAITING].includes(approvableStatusCode),\n 'approvable-badge--success': [ApprovableStatus.CODES.CODE_APPROVED, ApprovableStatus.CODES.CODE_VIEWED, ApprovableStatus.CODES.CODE_NOTICED].includes(approvableStatusCode),\n 'approvable-badge--danger': [ApprovableStatus.CODES.CODE_REJECTED].includes(approvableStatusCode),\n 'approvable-badge--muted': [ApprovableStatus.CODES.CODE_EXPIRED, ApprovableStatus.CODES.CODE_SOLVED].includes(approvableStatusCode),\n 'approvable-badge--empty': approvableStatusCode === ' - '\n }\n})\n\nconst badgeName = computed(() => {\n return props.label ? props.label : get(props.value, 'name', ' - ')\n})\n</script>\n","<template>\n <div v-if=\"approval.hasApprovable\" class=\"approvable\">\n <!-- A refresh has content to veil; an initial load has none, and gets the\n skeleton below instead. -->\n <div v-if=\"isLoading && approval.steps.length\" class=\"approvable-loading\">\n <span class=\"approvable-spinner\" />\n </div>\n\n <div class=\"approvable-header\">\n <h2 class=\"approvable-sr-only\">{{ title }}</h2>\n\n <template v-if=\"isInitialLoad\">\n <span aria-hidden=\"true\" class=\"approvable-skeleton-bar approvable-skeleton-bar--pill\" />\n <span class=\"approvable-skeleton-spacer\" />\n <span\n aria-hidden=\"true\"\n class=\"approvable-skeleton-bar approvable-skeleton-bar--soft\"\n style=\"width:104px;animation-delay:0.2s\"\n />\n </template>\n\n <template v-else>\n <approve-status-info\n v-if=\"showApprovableStatus\"\n :label=\"approval.statusName\"\n :value=\"approval.status\"\n />\n\n <span class=\"approvable-updated-at\">\n {{ approval.updatedAt }}\n </span>\n <button\n v-if=\"approval.id\"\n type=\"button\"\n class=\"approvable-history-btn\"\n :title=\"messages.historyTitle\"\n :aria-label=\"messages.historyTitle\"\n @click=\"historyOpen = true\"\n >\n {{ messages.history }}\n </button>\n </template>\n </div>\n\n <template v-if=\"isInitialLoad\">\n <span class=\"approvable-sr-only\" aria-live=\"polite\">{{ messages.loadingStatus }}</span>\n <div v-for=\"row in SKELETON_ROWS\" :key=\"row.delay\" aria-hidden=\"true\" class=\"approvable-skeleton-row\">\n <span class=\"approvable-skeleton-disc\" :style=\"{ animationDelay: row.delay }\" />\n <span class=\"approvable-skeleton-bar\" :style=\"{ width: row.name, animationDelay: row.delay }\" />\n <span class=\"approvable-skeleton-spacer\" />\n <span\n class=\"approvable-skeleton-bar approvable-skeleton-bar--soft\"\n :style=\"{ width: row.meta, animationDelay: row.metaDelay }\"\n />\n </div>\n <div class=\"approvable-footer\" aria-hidden=\"true\">\n <span class=\"approvable-skeleton-bar approvable-skeleton-bar--soft\" style=\"display:block;width:132px\" />\n </div>\n </template>\n\n <template v-else>\n <ol v-if=\"approval.steps.length\" :class=\"approvableStepsClass\">\n <approvable-step\n v-for=\"approvableStep of approval.steps\"\n :key=\"approvableStep.id\"\n :approvable=\"approval.approvable\"\n :resource=\"value\"\n :value=\"approvableStep\"\n @isLoading=\"(value) => (isLoading = value)\"\n @refresh=\"onRefresh\"\n >\n <template v-for=\"slot in Object.keys($slots)\" v-slot:[slot]=\"scoped\">\n <slot v-bind=\"scoped ?? {}\" :name=\"slot\" />\n </template>\n </approvable-step>\n </ol>\n\n <p v-if=\"progressLabel\" class=\"approvable-footer\">{{ progressLabel }}</p>\n </template>\n\n <Teleport to=\"body\">\n <div v-if=\"historyOpen\" class=\"approvable-dialog-backdrop\" @click.self=\"historyOpen = false\">\n <section\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"approvable-history-title\"\n class=\"approvable-dialog\"\n @keydown.esc=\"historyOpen = false\"\n >\n <header class=\"approvable-dialog-header\">\n <p class=\"approvable-dialog-eyebrow\">\n <svg aria-hidden=\"true\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" viewBox=\"0 0 16 16\">\n <path d=\"M9.6 4.5 6 8l3.6 3.5\" />\n </svg>\n {{ messages.history }}\n </p>\n <h2 id=\"approvable-history-title\" class=\"approvable-dialog-title\">{{ historyTitle }}</h2>\n <button\n type=\"button\"\n class=\"approvable-dialog-close\"\n :aria-label=\"messages.historyClose\"\n @click=\"historyOpen = false\"\n >\n <svg aria-hidden=\"true\" class=\"approvable-icon\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-width=\"2\" viewBox=\"0 0 16 16\">\n <path d=\"m5.2 5.2 5.6 5.6M10.8 5.2l-5.6 5.6\" />\n </svg>\n </button>\n </header>\n <div class=\"approvable-dialog-body\">\n <approvable-audit-timeline\n ref=\"auditTimeline\"\n :approvable-id=\"approval.id\"\n :show-header=\"false\"\n @loaded=\"(count) => (historyCount = count)\"\n />\n </div>\n </section>\n </div>\n </Teleport>\n </div>\n</template>\n\n<script setup>\nimport { ref, computed } from 'vue'\nimport { createApprovableViewModel, formatMessage } from '@stsdti/approvable-core'\nimport ApprovableAuditTimeline from './ApprovableAuditTimeline.vue'\nimport ApprovableStep from './ApprovableStep.vue'\nimport ApproveStatusInfo from './ApproveStatusInfo.vue'\nimport { useMessages } from '../../messages.js'\n\nconst props = defineProps({\n value: {},\n showApprovableStatus: { type: Boolean, default: true },\n title: { default: 'Approval' },\n isDirectionRow: { default: false }\n})\n\nconst emits = defineEmits(['refresh', 'isLoading'])\n\nconst isLoading = ref(false)\nconst auditTimeline = ref(null)\nconst historyOpen = ref(false)\nconst historyCount = ref(null)\n\nconst messages = useMessages()\n\n// Widths and stagger for the placeholder rows. Kept as data so the skeleton is\n// three rows of varied length rather than three identical ones, which reads as\n// a frozen list instead of a loading one.\nconst SKELETON_ROWS = [\n { name: '118px', meta: '56px', delay: '0s', metaDelay: '0.15s' },\n { name: '96px', meta: '72px', delay: '0.1s', metaDelay: '0.25s' },\n { name: '78px', meta: '48px', delay: '0.2s', metaDelay: '0.35s' }\n]\n\nconst approval = computed(() => createApprovableViewModel(props.value))\n\n/** Names the dialog, and once the history has loaded, counts it. */\nconst historyTitle = computed(() => (\n historyCount.value === null\n ? messages.historyTitle\n : formatMessage(messages.eventCount, { count: historyCount.value })\n))\n\n/** Nothing to veil yet, so the panel shows its own shape instead. */\nconst isInitialLoad = computed(() => isLoading.value && !approval.value.steps.length)\n\nconst approvableStepsClass = computed(() => ({\n 'approvable-steps': true,\n 'approvable-steps--row': props.isDirectionRow\n}))\n\n/** \"Step 2 of 3 — awaiting Priya Raman\", with the tail dropped when nothing is pending. */\nconst progressLabel = computed(() => {\n const { activeStepNumber, visibleStepCount, activeApproverName } = approval.value\n\n if (!activeStepNumber || !visibleStepCount) {\n return null\n }\n\n const progress = formatMessage(messages.stepProgress, {\n current: activeStepNumber,\n total: visibleStepCount\n })\n\n if (!activeApproverName) {\n return progress\n }\n\n return `${progress} — ${formatMessage(messages.awaitingApprover, { name: activeApproverName })}`\n})\n\nconst onRefresh = () => {\n auditTimeline.value?.refresh()\n emits('refresh')\n}\n</script>\n","<template>\n <div v-if=\"hasApprovableButtons\" class=\"approvable-actions\">\n <hr class=\"approvable-divider\" />\n <div class=\"approvable-actions-list\">\n <button\n v-for=\"approvableButton in approvableButtons\"\n :key=\"approvableButton.code\"\n :title=\"approvableButton.tooltip\"\n class=\"approvable-btn\"\n type=\"button\"\n @click=\"onApproveStatusChange(approvableButton)\"\n >\n <slot name=\"icon\" :button=\"approvableButton\">\n <component\n :is=\"icons[approvableButton.icon]\"\n v-if=\"isRegisteredIcon(icons, approvableButton.icon)\"\n class=\"approvable-btn-icon\"\n />\n <img\n v-else-if=\"isUrlIcon(approvableButton.icon)\"\n :src=\"approvableButton.icon\"\n alt=\"\"\n class=\"approvable-btn-icon\"\n />\n <i v-else-if=\"isClassIcon(approvableButton.icon)\" :class=\"approvableButton.icon\"></i>\n </slot>\n {{ approvableButton.text }}\n </button>\n </div>\n </div>\n</template>\n\n<script setup>\nimport { ref, computed } from 'vue'\nimport { ApprovableStepRepository, get, isSuccessResponse, notifySuccess } from '@stsdti/approvable-core'\nimport { isClassIcon, isRegisteredIcon, isUrlIcon, useIconRegistry } from '../../icons.js'\nimport { useMessages } from '../../messages.js'\n\nconst props = defineProps({\n value: {\n required: true\n }\n})\nconst emits = defineEmits(['isLoading', 'refresh'])\n\nconst isLoading = ref(false)\n\nconst approvableButtons = computed(() => {\n return get(props.value, 'buttons', [])\n})\nconst hasApprovableButtons = computed(() => {\n if (!approvableButtons.value) {\n return false\n }\n return approvableButtons.value.length > 0\n})\n\nconst icons = useIconRegistry()\nconst messages = useMessages()\n\nconst onApproveStatusChange = (button) => {\n let approvableId = get(props.value, 'id')\n\n if (!approvableId) {\n return\n }\n onUpdateStatus(approvableId, button)\n}\nconst onUpdateStatus = async (id, button) => {\n emits('isLoading', true)\n isLoading.value = true\n const response = await new ApprovableStepRepository().updateApproveStatus(id, button)\n\n if (isSuccessResponse(response)) {\n notifySuccess(messages.actionSucceeded)\n }\n emits('isLoading', false)\n emits('refresh')\n}\n</script>\n","<template>\n <label class=\"approvable-select\">\n <span v-if=\"label\" class=\"approvable-select-label\">{{ label }}</span>\n <select\n :value=\"selectedKey\"\n class=\"approvable-select-input\"\n v-bind=\"$attrs\"\n @change=\"onChange\"\n >\n <option value=\"\">-</option>\n <option v-for=\"option in options\" :key=\"optionKey(option)\" :value=\"optionKey(option)\">\n {{ optionName(option) }}\n </option>\n </select>\n </label>\n</template>\n\n<script setup>\nimport { computed, onMounted, ref } from 'vue'\nimport { ApprovableStatusRepository, get } from '@stsdti/approvable-core'\n\ndefineOptions({\n inheritAttrs: false\n})\n\nconst emit = defineEmits(['mounted'])\nconst modelValue = defineModel()\n\nconst props = defineProps({\n getList: {},\n label: {\n default: 'Status'\n }\n})\n\nconst options = ref([])\n\nconst getListDefault = async (search) => {\n let filters = [{ field: 'search', value: search }]\n return await new ApprovableStatusRepository().fetchAll({ filters })\n}\n\nconst optionKey = (option) => String(get(option, 'id') ?? get(option, 'code', ''))\nconst optionName = (option) => get(option, 'name') ?? get(option, 'text', '')\n\nconst selectedKey = computed(() => {\n return modelValue.value ? optionKey(modelValue.value) : ''\n})\n\nconst onChange = (event) => {\n const key = event.target.value\n modelValue.value = options.value.find((option) => optionKey(option) === key) ?? null\n}\n\nconst refresh = async (search = null) => {\n const list = await (props.getList ?? getListDefault)(search)\n options.value = Array.isArray(list) ? list : []\n}\n\nonMounted(async () => {\n await refresh()\n emit('mounted', { refresh, options })\n})\n</script>\n","<template>\n <div class=\"approvable-select-option\">\n <span>{{ displayName }}</span>\n </div>\n</template>\n\n\n<script setup>\nimport { computed } from 'vue'\nimport { get } from '@stsdti/approvable-core'\n\nconst props = defineProps({\n value: {}\n})\nconst displayName = computed(() => get(props.value, 'name'))\n</script>\n","/**\n * @stsdti/approvable-vue\n *\n * Vue 3 components for laravel-approvable. All behaviour lives in\n * @stsdti/approvable-core; this package renders it.\n *\n * Components ship unstyled and emit `.approvable-*` class names. Import the\n * theme to give them a look — one stylesheet, light and dark:\n *\n * import '@stsdti/approvable-vue/themes/approvable.css'\n */\n\nimport Approvable from './components/approvable/Approvable.vue'\nimport ApprovableStep from './components/approvable/ApprovableStep.vue'\nimport ApprovableButtons from './components/approvable/ApprovableButtons.vue'\nimport ApprovableStepComment from './components/approvable/ApprovableStepComment.vue'\nimport ApprovableAuditTimeline from './components/approvable/ApprovableAuditTimeline.vue'\nimport ApproveStatusInfo from './components/approvable/ApproveStatusInfo.vue'\nimport ApprovableStatusSelect from './components/select/approvable-status-select/ApprovableStatusSelect.vue'\nimport ApprovableStatusSelectOption from './components/select/approvable-status-select/ApprovableStatusSelectOption.vue'\n\nimport { APPROVABLE_LINK_COMPONENT } from './config.js'\nimport { APPROVABLE_ICON_REGISTRY } from './icons.js'\nimport { APPROVABLE_MESSAGES } from './messages.js'\nimport {\n registerApprovableActionRenderer,\n unregisterApprovableActionRenderer,\n approvableActionRenderer,\n approvableActionSlotName\n} from './components/approvable/action-renderers.js'\n\nexport {\n Approvable,\n ApprovableStep,\n ApprovableButtons,\n ApprovableStepComment,\n ApprovableAuditTimeline,\n ApproveStatusInfo,\n ApprovableStatusSelect,\n ApprovableStatusSelectOption\n}\n\nexport {\n registerApprovableActionRenderer,\n unregisterApprovableActionRenderer,\n approvableActionRenderer,\n approvableActionSlotName\n}\n\nexport { APPROVABLE_LINK_COMPONENT, useLinkComponent, linkProps } from './config.js'\nexport {\n APPROVABLE_ICON_REGISTRY,\n useIconRegistry,\n isRegisteredIcon,\n isUrlIcon,\n isClassIcon\n} from './icons.js'\nexport { APPROVABLE_MESSAGES, useMessages } from './messages.js'\n\nconst components = {\n Approvable,\n ApprovableStep,\n ApprovableButtons,\n ApprovableStepComment,\n ApprovableAuditTimeline,\n ApproveStatusInfo,\n ApprovableStatusSelect,\n ApprovableStatusSelectOption\n}\n\n/**\n * Vue plugin, for applications that prefer global registration.\n *\n * app.use(ApprovableVue, {\n * linkComponent: RouterLink,\n * icons: { approve: CheckIcon },\n * messages: { commentSaved: 'Comentariul a fost adăugat.' }\n * })\n *\n * `linkComponent` is what a navigating button renders as. It defaults to a\n * plain anchor so the package works without a router installed.\n *\n * `icons` maps a button's `icon` name to a component. Icons are names, never\n * raw SVG rendered with v-html — that would let anyone who can edit a workflow\n * run script in every approver's browser.\n *\n * `messages` overrides the user-facing strings, which are English by default.\n */\nexport default {\n install (app, { linkComponent = null, icons = null, messages = null, register = true } = {}) {\n if (linkComponent) {\n app.provide(APPROVABLE_LINK_COMPONENT, linkComponent)\n }\n\n if (icons) {\n app.provide(APPROVABLE_ICON_REGISTRY, icons)\n }\n\n if (messages) {\n app.provide(APPROVABLE_MESSAGES, messages)\n }\n\n if (register) {\n for (const [name, component] of Object.entries(components)) {\n app.component(name, component)\n }\n }\n }\n}\n"],"names":["APPROVABLE_MESSAGES","useMessages","mergeMessages","inject","props","__props","emits","__emit","messages","repository","ApprovableAuditRepository","audits","ref","loading","error","FIELD_LABELS","ICONS","QUIET_KINDS","groups","computed","stepAudits","audit","grouped","key","entries","kind","auditKind","details","changeRows","a","b","button","_a","_b","_c","statusChanged","before","after","operationTitle","label","_e","_d","_f","actorLabel","actor","entry","oldValues","newValues","row","hasPreviousValue","change","displayValue","value","text","formatDate","date","refresh","response","data","exception","eventSummary","formatMessage","watch","__expose","_createElementBlock","_openBlock","_hoisted_1","_createElementVNode","_hoisted_2","_toDisplayString","_unref","_hoisted_3","_hoisted_4","_hoisted_5","_cache","_hoisted_6","_Fragment","_hoisted_8","_renderList","group","_normalizeClass","d","i","_hoisted_11","_hoisted_12","_hoisted_13","_hoisted_14","_hoisted_15","_hoisted_16","_hoisted_17","_hoisted_18","_hoisted_19","_hoisted_20","_hoisted_21","_hoisted_7","rootRef","useTemplateRef","textareaRef","isOpen","isLoading","comment","commentedBy","get","onToggle","hide","show","nextTick","resizeTextarea","textarea","onDocumentClick","event","onDocumentKeydown","onMounted","onBeforeUnmount","onComment","notifyError","ApprovableStepRepository","isSuccessResponse","notifySuccess","$event","registerApprovableActionRenderer","name","component","registerActionRenderer","markRaw","APPROVABLE_LINK_COMPONENT","useLinkComponent","linkProps","target","APPROVABLE_ICON_REGISTRY","useIconRegistry","linkComponent","isCommentExpanded","step","createStepViewModel","tone","approvableStatusTone","hasActions","showStatus","rowClass","GLYPHS","DISC_MODIFIERS","glyph","approvableStepGlyph","discGlyph","discClass","commentText","buttonClass","buttonRenderer","approvableActionRenderer","onApproveStatusChange","buttonOrId","result","performStepAction","_renderSlot","_ctx","_hoisted_9","_hoisted_10","index","_createBlock","_resolveDynamicComponent","_mergeProps","isClassIcon","_createVNode","ApprovableStepComment","badgeClass","approvableStatusCode","ApprovableStatus","badgeName","auditTimeline","historyOpen","historyCount","SKELETON_ROWS","approval","createApprovableViewModel","historyTitle","isInitialLoad","approvableStepsClass","progressLabel","activeStepNumber","visibleStepCount","activeApproverName","progress","onRefresh","ApproveStatusInfo","_normalizeStyle","approvableStep","ApprovableStep","$slots","slot","_withCtx","scoped","_Teleport","ApprovableAuditTimeline","count","approvableButtons","hasApprovableButtons","icons","approvableId","onUpdateStatus","id","approvableButton","isRegisteredIcon","isUrlIcon","emit","modelValue","_useModel","options","getListDefault","search","filters","ApprovableStatusRepository","optionKey","option","optionName","selectedKey","onChange","list","$attrs","displayName","components","Approvable","ApprovableButtons","ApprovableStatusSelect","ApprovableStatusSelectOption","app","register"],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@stsdti/approvable-vue",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Vue 3 components for laravel-approvable: approval trails, step actions, comments and the audit timeline.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"module": "./dist/approvable-vue.mjs",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": "./dist/approvable-vue.mjs",
|
|
10
|
+
"./themes/*.css": "./src/themes/*.css",
|
|
11
|
+
"./src/*": "./src/*",
|
|
12
|
+
"./package.json": "./package.json"
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist",
|
|
16
|
+
"src",
|
|
17
|
+
"README.md",
|
|
18
|
+
"LICENSE"
|
|
19
|
+
],
|
|
20
|
+
"sideEffects": [
|
|
21
|
+
"*.css"
|
|
22
|
+
],
|
|
23
|
+
"repository": {
|
|
24
|
+
"type": "git",
|
|
25
|
+
"url": "git+https://github.com/stsdti/laravel-approvable.git",
|
|
26
|
+
"directory": "packages/frontends/vue"
|
|
27
|
+
},
|
|
28
|
+
"homepage": "https://github.com/stsdti/laravel-approvable/tree/main/packages/frontends/vue",
|
|
29
|
+
"keywords": [
|
|
30
|
+
"laravel",
|
|
31
|
+
"vue",
|
|
32
|
+
"approval",
|
|
33
|
+
"workflow",
|
|
34
|
+
"approvable"
|
|
35
|
+
],
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@stsdti/approvable-core": "^0.1.0"
|
|
38
|
+
},
|
|
39
|
+
"peerDependencies": {
|
|
40
|
+
"vue": "^3.3.0"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@vitejs/plugin-vue": "^5.2.0",
|
|
44
|
+
"vite": "^6.0.0",
|
|
45
|
+
"vue": "^3.5.0"
|
|
46
|
+
},
|
|
47
|
+
"scripts": {
|
|
48
|
+
"test": "node --test test/*.test.js",
|
|
49
|
+
"build": "vite build",
|
|
50
|
+
"prepublishOnly": "npm run build"
|
|
51
|
+
},
|
|
52
|
+
"publishConfig": {
|
|
53
|
+
"access": "public"
|
|
54
|
+
},
|
|
55
|
+
"engines": {
|
|
56
|
+
"node": ">=20"
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div v-if="approval.hasApprovable" class="approvable">
|
|
3
|
+
<!-- A refresh has content to veil; an initial load has none, and gets the
|
|
4
|
+
skeleton below instead. -->
|
|
5
|
+
<div v-if="isLoading && approval.steps.length" class="approvable-loading">
|
|
6
|
+
<span class="approvable-spinner" />
|
|
7
|
+
</div>
|
|
8
|
+
|
|
9
|
+
<div class="approvable-header">
|
|
10
|
+
<h2 class="approvable-sr-only">{{ title }}</h2>
|
|
11
|
+
|
|
12
|
+
<template v-if="isInitialLoad">
|
|
13
|
+
<span aria-hidden="true" class="approvable-skeleton-bar approvable-skeleton-bar--pill" />
|
|
14
|
+
<span class="approvable-skeleton-spacer" />
|
|
15
|
+
<span
|
|
16
|
+
aria-hidden="true"
|
|
17
|
+
class="approvable-skeleton-bar approvable-skeleton-bar--soft"
|
|
18
|
+
style="width:104px;animation-delay:0.2s"
|
|
19
|
+
/>
|
|
20
|
+
</template>
|
|
21
|
+
|
|
22
|
+
<template v-else>
|
|
23
|
+
<approve-status-info
|
|
24
|
+
v-if="showApprovableStatus"
|
|
25
|
+
:label="approval.statusName"
|
|
26
|
+
:value="approval.status"
|
|
27
|
+
/>
|
|
28
|
+
|
|
29
|
+
<span class="approvable-updated-at">
|
|
30
|
+
{{ approval.updatedAt }}
|
|
31
|
+
</span>
|
|
32
|
+
<button
|
|
33
|
+
v-if="approval.id"
|
|
34
|
+
type="button"
|
|
35
|
+
class="approvable-history-btn"
|
|
36
|
+
:title="messages.historyTitle"
|
|
37
|
+
:aria-label="messages.historyTitle"
|
|
38
|
+
@click="historyOpen = true"
|
|
39
|
+
>
|
|
40
|
+
{{ messages.history }}
|
|
41
|
+
</button>
|
|
42
|
+
</template>
|
|
43
|
+
</div>
|
|
44
|
+
|
|
45
|
+
<template v-if="isInitialLoad">
|
|
46
|
+
<span class="approvable-sr-only" aria-live="polite">{{ messages.loadingStatus }}</span>
|
|
47
|
+
<div v-for="row in SKELETON_ROWS" :key="row.delay" aria-hidden="true" class="approvable-skeleton-row">
|
|
48
|
+
<span class="approvable-skeleton-disc" :style="{ animationDelay: row.delay }" />
|
|
49
|
+
<span class="approvable-skeleton-bar" :style="{ width: row.name, animationDelay: row.delay }" />
|
|
50
|
+
<span class="approvable-skeleton-spacer" />
|
|
51
|
+
<span
|
|
52
|
+
class="approvable-skeleton-bar approvable-skeleton-bar--soft"
|
|
53
|
+
:style="{ width: row.meta, animationDelay: row.metaDelay }"
|
|
54
|
+
/>
|
|
55
|
+
</div>
|
|
56
|
+
<div class="approvable-footer" aria-hidden="true">
|
|
57
|
+
<span class="approvable-skeleton-bar approvable-skeleton-bar--soft" style="display:block;width:132px" />
|
|
58
|
+
</div>
|
|
59
|
+
</template>
|
|
60
|
+
|
|
61
|
+
<template v-else>
|
|
62
|
+
<ol v-if="approval.steps.length" :class="approvableStepsClass">
|
|
63
|
+
<approvable-step
|
|
64
|
+
v-for="approvableStep of approval.steps"
|
|
65
|
+
:key="approvableStep.id"
|
|
66
|
+
:approvable="approval.approvable"
|
|
67
|
+
:resource="value"
|
|
68
|
+
:value="approvableStep"
|
|
69
|
+
@isLoading="(value) => (isLoading = value)"
|
|
70
|
+
@refresh="onRefresh"
|
|
71
|
+
>
|
|
72
|
+
<template v-for="slot in Object.keys($slots)" v-slot:[slot]="scoped">
|
|
73
|
+
<slot v-bind="scoped ?? {}" :name="slot" />
|
|
74
|
+
</template>
|
|
75
|
+
</approvable-step>
|
|
76
|
+
</ol>
|
|
77
|
+
|
|
78
|
+
<p v-if="progressLabel" class="approvable-footer">{{ progressLabel }}</p>
|
|
79
|
+
</template>
|
|
80
|
+
|
|
81
|
+
<Teleport to="body">
|
|
82
|
+
<div v-if="historyOpen" class="approvable-dialog-backdrop" @click.self="historyOpen = false">
|
|
83
|
+
<section
|
|
84
|
+
role="dialog"
|
|
85
|
+
aria-modal="true"
|
|
86
|
+
aria-labelledby="approvable-history-title"
|
|
87
|
+
class="approvable-dialog"
|
|
88
|
+
@keydown.esc="historyOpen = false"
|
|
89
|
+
>
|
|
90
|
+
<header class="approvable-dialog-header">
|
|
91
|
+
<p class="approvable-dialog-eyebrow">
|
|
92
|
+
<svg aria-hidden="true" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 16 16">
|
|
93
|
+
<path d="M9.6 4.5 6 8l3.6 3.5" />
|
|
94
|
+
</svg>
|
|
95
|
+
{{ messages.history }}
|
|
96
|
+
</p>
|
|
97
|
+
<h2 id="approvable-history-title" class="approvable-dialog-title">{{ historyTitle }}</h2>
|
|
98
|
+
<button
|
|
99
|
+
type="button"
|
|
100
|
+
class="approvable-dialog-close"
|
|
101
|
+
:aria-label="messages.historyClose"
|
|
102
|
+
@click="historyOpen = false"
|
|
103
|
+
>
|
|
104
|
+
<svg aria-hidden="true" class="approvable-icon" fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="2" viewBox="0 0 16 16">
|
|
105
|
+
<path d="m5.2 5.2 5.6 5.6M10.8 5.2l-5.6 5.6" />
|
|
106
|
+
</svg>
|
|
107
|
+
</button>
|
|
108
|
+
</header>
|
|
109
|
+
<div class="approvable-dialog-body">
|
|
110
|
+
<approvable-audit-timeline
|
|
111
|
+
ref="auditTimeline"
|
|
112
|
+
:approvable-id="approval.id"
|
|
113
|
+
:show-header="false"
|
|
114
|
+
@loaded="(count) => (historyCount = count)"
|
|
115
|
+
/>
|
|
116
|
+
</div>
|
|
117
|
+
</section>
|
|
118
|
+
</div>
|
|
119
|
+
</Teleport>
|
|
120
|
+
</div>
|
|
121
|
+
</template>
|
|
122
|
+
|
|
123
|
+
<script setup>
|
|
124
|
+
import { ref, computed } from 'vue'
|
|
125
|
+
import { createApprovableViewModel, formatMessage } from '@stsdti/approvable-core'
|
|
126
|
+
import ApprovableAuditTimeline from './ApprovableAuditTimeline.vue'
|
|
127
|
+
import ApprovableStep from './ApprovableStep.vue'
|
|
128
|
+
import ApproveStatusInfo from './ApproveStatusInfo.vue'
|
|
129
|
+
import { useMessages } from '../../messages.js'
|
|
130
|
+
|
|
131
|
+
const props = defineProps({
|
|
132
|
+
value: {},
|
|
133
|
+
showApprovableStatus: { type: Boolean, default: true },
|
|
134
|
+
title: { default: 'Approval' },
|
|
135
|
+
isDirectionRow: { default: false }
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
const emits = defineEmits(['refresh', 'isLoading'])
|
|
139
|
+
|
|
140
|
+
const isLoading = ref(false)
|
|
141
|
+
const auditTimeline = ref(null)
|
|
142
|
+
const historyOpen = ref(false)
|
|
143
|
+
const historyCount = ref(null)
|
|
144
|
+
|
|
145
|
+
const messages = useMessages()
|
|
146
|
+
|
|
147
|
+
// Widths and stagger for the placeholder rows. Kept as data so the skeleton is
|
|
148
|
+
// three rows of varied length rather than three identical ones, which reads as
|
|
149
|
+
// a frozen list instead of a loading one.
|
|
150
|
+
const SKELETON_ROWS = [
|
|
151
|
+
{ name: '118px', meta: '56px', delay: '0s', metaDelay: '0.15s' },
|
|
152
|
+
{ name: '96px', meta: '72px', delay: '0.1s', metaDelay: '0.25s' },
|
|
153
|
+
{ name: '78px', meta: '48px', delay: '0.2s', metaDelay: '0.35s' }
|
|
154
|
+
]
|
|
155
|
+
|
|
156
|
+
const approval = computed(() => createApprovableViewModel(props.value))
|
|
157
|
+
|
|
158
|
+
/** Names the dialog, and once the history has loaded, counts it. */
|
|
159
|
+
const historyTitle = computed(() => (
|
|
160
|
+
historyCount.value === null
|
|
161
|
+
? messages.historyTitle
|
|
162
|
+
: formatMessage(messages.eventCount, { count: historyCount.value })
|
|
163
|
+
))
|
|
164
|
+
|
|
165
|
+
/** Nothing to veil yet, so the panel shows its own shape instead. */
|
|
166
|
+
const isInitialLoad = computed(() => isLoading.value && !approval.value.steps.length)
|
|
167
|
+
|
|
168
|
+
const approvableStepsClass = computed(() => ({
|
|
169
|
+
'approvable-steps': true,
|
|
170
|
+
'approvable-steps--row': props.isDirectionRow
|
|
171
|
+
}))
|
|
172
|
+
|
|
173
|
+
/** "Step 2 of 3 — awaiting Priya Raman", with the tail dropped when nothing is pending. */
|
|
174
|
+
const progressLabel = computed(() => {
|
|
175
|
+
const { activeStepNumber, visibleStepCount, activeApproverName } = approval.value
|
|
176
|
+
|
|
177
|
+
if (!activeStepNumber || !visibleStepCount) {
|
|
178
|
+
return null
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const progress = formatMessage(messages.stepProgress, {
|
|
182
|
+
current: activeStepNumber,
|
|
183
|
+
total: visibleStepCount
|
|
184
|
+
})
|
|
185
|
+
|
|
186
|
+
if (!activeApproverName) {
|
|
187
|
+
return progress
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return `${progress} — ${formatMessage(messages.awaitingApprover, { name: activeApproverName })}`
|
|
191
|
+
})
|
|
192
|
+
|
|
193
|
+
const onRefresh = () => {
|
|
194
|
+
auditTimeline.value?.refresh()
|
|
195
|
+
emits('refresh')
|
|
196
|
+
}
|
|
197
|
+
</script>
|