dou-ui 0.1.0-alpha.3 → 0.1.0-alpha.5

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 (142) hide show
  1. package/dist/components/card/card.js.map +1 -1
  2. package/dist/components/card/card.vue_vue_type_script_setup_true_lang.js +45 -19
  3. package/dist/components/card/card.vue_vue_type_script_setup_true_lang.js.map +1 -1
  4. package/dist/components/chat-confirm/chat-confirm.js.map +1 -1
  5. package/dist/components/chat-confirm/chat-confirm.vue_vue_type_script_setup_true_lang.js +2 -3
  6. package/dist/components/chat-confirm/chat-confirm.vue_vue_type_script_setup_true_lang.js.map +1 -1
  7. package/dist/components/chat-context-meter/chat-context-meter.js +19 -2
  8. package/dist/components/chat-context-meter/chat-context-meter.js.map +1 -1
  9. package/dist/components/chat-context-meter/chat-context-meter.vue_vue_type_script_setup_true_lang.js +43 -42
  10. package/dist/components/chat-context-meter/chat-context-meter.vue_vue_type_script_setup_true_lang.js.map +1 -1
  11. package/dist/components/chat-context-meter/chat-context-meter2.js.map +1 -1
  12. package/dist/components/chat-context-meter/index.js +2 -1
  13. package/dist/components/chat-context-meter/index.js.map +1 -1
  14. package/dist/components/chat-context-meter/style.js +1 -3
  15. package/dist/components/chat-input/chat-input.js.map +1 -1
  16. package/dist/components/chat-input/chat-input.vue_vue_type_script_setup_true_lang.js +75 -7
  17. package/dist/components/chat-input/chat-input.vue_vue_type_script_setup_true_lang.js.map +1 -1
  18. package/dist/components/chat-input/chat-input2.js.map +1 -1
  19. package/dist/components/chat-list/chat-list.js +9 -4
  20. package/dist/components/chat-list/chat-list.js.map +1 -1
  21. package/dist/components/chat-list/chat-list.vue_vue_type_script_setup_true_lang.js +34 -0
  22. package/dist/components/chat-list/chat-list.vue_vue_type_script_setup_true_lang.js.map +1 -1
  23. package/dist/components/chat-list/chat-list2.js +6 -0
  24. package/dist/components/chat-list/chat-list2.js.map +1 -0
  25. package/dist/components/chat-list/index.js +1 -1
  26. package/dist/components/chat-message/chat-message.js.map +1 -1
  27. package/dist/components/chat-message/chat-message.vue_vue_type_script_setup_true_lang.js +33 -8
  28. package/dist/components/chat-message/chat-message.vue_vue_type_script_setup_true_lang.js.map +1 -1
  29. package/dist/components/chat-message/chat-message2.js.map +1 -1
  30. package/dist/components/chat-message/style.js +1 -0
  31. package/dist/components/chat-question/chat-question.js +6 -0
  32. package/dist/components/chat-question/chat-question.js.map +1 -0
  33. package/dist/components/chat-question/chat-question.vue_vue_type_script_setup_true_lang.js +116 -0
  34. package/dist/components/chat-question/chat-question.vue_vue_type_script_setup_true_lang.js.map +1 -0
  35. package/dist/components/chat-question/index.js +7 -0
  36. package/dist/components/chat-question/index.js.map +1 -0
  37. package/dist/components/chat-question/style.d.ts +1 -0
  38. package/dist/components/chat-question/style.js +2 -0
  39. package/dist/components/comment-thread/comment-thread.js.map +1 -1
  40. package/dist/components/comment-thread/comment-thread.vue_vue_type_script_setup_true_lang.js +5 -1
  41. package/dist/components/comment-thread/comment-thread.vue_vue_type_script_setup_true_lang.js.map +1 -1
  42. package/dist/components/config-provider/use-config.js +5 -2
  43. package/dist/components/config-provider/use-config.js.map +1 -1
  44. package/dist/components/copy-button/copy-button.vue_vue_type_script_setup_true_lang.js +1 -1
  45. package/dist/components/dialog/functional.js +3 -7
  46. package/dist/components/dialog/functional.js.map +1 -1
  47. package/dist/components/dialog/index.js +4 -3
  48. package/dist/components/dialog/index.js.map +1 -1
  49. package/dist/components/image/image.js.map +1 -1
  50. package/dist/components/image/image.vue_vue_type_script_setup_true_lang.js +10 -1
  51. package/dist/components/image/image.vue_vue_type_script_setup_true_lang.js.map +1 -1
  52. package/dist/components/link/link.js.map +1 -1
  53. package/dist/components/link/link.vue_vue_type_script_setup_true_lang.js +116 -31
  54. package/dist/components/link/link.vue_vue_type_script_setup_true_lang.js.map +1 -1
  55. package/dist/components/menu/menu-actions.js +65 -0
  56. package/dist/components/menu/menu-actions.js.map +1 -0
  57. package/dist/components/menu/menu-item.js.map +1 -1
  58. package/dist/components/menu/menu-item.vue_vue_type_script_setup_true_lang.js +50 -12
  59. package/dist/components/menu/menu-item.vue_vue_type_script_setup_true_lang.js.map +1 -1
  60. package/dist/components/menu/menu-list.js.map +1 -1
  61. package/dist/components/menu/menu-list.vue_vue_type_script_setup_true_lang.js +32 -17
  62. package/dist/components/menu/menu-list.vue_vue_type_script_setup_true_lang.js.map +1 -1
  63. package/dist/components/menu/menu-popup.js.map +1 -1
  64. package/dist/components/menu/menu-popup.vue_vue_type_script_setup_true_lang.js +37 -8
  65. package/dist/components/menu/menu-popup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  66. package/dist/components/menu/menu.js +1 -0
  67. package/dist/components/menu/menu.js.map +1 -1
  68. package/dist/components/menu/menu.vue_vue_type_script_setup_true_lang.js +5 -1
  69. package/dist/components/menu/menu.vue_vue_type_script_setup_true_lang.js.map +1 -1
  70. package/dist/components/menu/menu2.js.map +1 -1
  71. package/dist/components/node-graph/layout.js +123 -15
  72. package/dist/components/node-graph/layout.js.map +1 -1
  73. package/dist/components/popover/popover.js.map +1 -1
  74. package/dist/components/popover/popover.vue_vue_type_script_setup_true_lang.js +3 -3
  75. package/dist/components/popover/popover.vue_vue_type_script_setup_true_lang.js.map +1 -1
  76. package/dist/components/toast/index.js +5 -4
  77. package/dist/components/toast/index.js.map +1 -1
  78. package/dist/components/toast/store.js +1 -9
  79. package/dist/components/toast/store.js.map +1 -1
  80. package/dist/components/tooltip/tooltip.js.map +1 -1
  81. package/dist/components/tooltip/tooltip.vue_vue_type_script_setup_true_lang.js +1 -1
  82. package/dist/components/tooltip/tooltip.vue_vue_type_script_setup_true_lang.js.map +1 -1
  83. package/dist/components/virtual-list/virtual-list.js +7 -1
  84. package/dist/components/virtual-list/virtual-list.js.map +1 -1
  85. package/dist/components/virtual-list/virtual-list.vue_vue_type_script_setup_true_lang.js +2 -7
  86. package/dist/components/virtual-list/virtual-list.vue_vue_type_script_setup_true_lang.js.map +1 -1
  87. package/dist/components/virtual-list/virtual-list2.js.map +1 -1
  88. package/dist/index.js +7 -5
  89. package/dist/index.js.map +1 -1
  90. package/dist/locale/en.js +1 -0
  91. package/dist/locale/en.js.map +1 -1
  92. package/dist/locale/zh-cn.js +1 -0
  93. package/dist/locale/zh-cn.js.map +1 -1
  94. package/dist/locale/zh-tw.js +1 -0
  95. package/dist/locale/zh-tw.js.map +1 -1
  96. package/dist/plugin.js +6 -2
  97. package/dist/plugin.js.map +1 -1
  98. package/dist/style.css +1 -1
  99. package/dist/types/components/card/card.d.ts +6 -1
  100. package/dist/types/components/chat-context-meter/chat-context-meter.d.ts +23 -3
  101. package/dist/types/components/chat-context-meter/index.d.ts +1 -0
  102. package/dist/types/components/chat-input/chat-input.d.ts +33 -3
  103. package/dist/types/components/chat-input/chat-input.vue.d.ts +7 -0
  104. package/dist/types/components/chat-input/index.d.ts +20 -0
  105. package/dist/types/components/chat-list/chat-list.d.ts +19 -1
  106. package/dist/types/components/chat-message/chat-message.d.ts +32 -2
  107. package/dist/types/components/chat-message/chat-message.vue.d.ts +4 -1
  108. package/dist/types/components/chat-message/index.d.ts +8 -0
  109. package/dist/types/components/chat-question/chat-question.d.ts +43 -0
  110. package/dist/types/components/chat-question/chat-question.vue.d.ts +18 -0
  111. package/dist/types/components/chat-question/index.d.ts +43 -0
  112. package/dist/types/components/comment-thread/comment-thread.d.ts +6 -0
  113. package/dist/types/components/comment-thread/comment-thread.vue.d.ts +1 -0
  114. package/dist/types/components/comment-thread/index.d.ts +3 -0
  115. package/dist/types/components/dialog/functional.d.ts +0 -3
  116. package/dist/types/components/dialog/index.d.ts +1 -1
  117. package/dist/types/components/dropdown/dropdown.vue.d.ts +1 -1
  118. package/dist/types/components/dropdown/index.d.ts +3 -3
  119. package/dist/types/components/image/image.d.ts +9 -0
  120. package/dist/types/components/index.d.ts +1 -0
  121. package/dist/types/components/link/index.d.ts +3 -0
  122. package/dist/types/components/link/link.d.ts +24 -3
  123. package/dist/types/components/link/link.vue.d.ts +1 -0
  124. package/dist/types/components/menu/index.d.ts +3 -0
  125. package/dist/types/components/menu/menu-actions.d.ts +26 -0
  126. package/dist/types/components/menu/menu-item.vue.d.ts +6 -0
  127. package/dist/types/components/menu/menu.d.ts +32 -0
  128. package/dist/types/components/menu/menu.vue.d.ts +1 -0
  129. package/dist/types/components/node-graph/layout.d.ts +26 -0
  130. package/dist/types/components/popover/index.d.ts +3 -3
  131. package/dist/types/components/popover/popover.vue.d.ts +1 -1
  132. package/dist/types/components/select/index.d.ts +3 -3
  133. package/dist/types/components/select/select.vue.d.ts +1 -1
  134. package/dist/types/components/toast/index.d.ts +0 -2
  135. package/dist/types/components/toast/store.d.ts +0 -4
  136. package/dist/types/components/virtual-list/virtual-list.d.ts +2 -0
  137. package/dist/types/index.d.ts +1 -0
  138. package/dist/types/locale/types.d.ts +3 -1
  139. package/dist/types/utils/app-context.d.ts +14 -0
  140. package/dist/utils/app-context.js +22 -0
  141. package/dist/utils/app-context.js.map +1 -0
  142. package/package.json +3 -3
@@ -1 +1 @@
1
- {"version":3,"file":"card.js","names":["_sfc_main"],"sources":["../../../src/components/card/card.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { useNamespace } from '../../utils/namespace'\nimport type { CardProps, CardSlots } from './card'\n\ndefineOptions({ name: 'DouCard' })\n\nconst props = withDefaults(defineProps<CardProps>(), {\n padding: 'md',\n raised: false,\n interactive: false,\n as: 'div',\n})\nconst slots = defineSlots<CardSlots>()\n\nconst ns = useNamespace('card')\n\nconst hasHeader = computed(\n () => !!(slots.header || slots.extra || props.title || props.description),\n)\n\nconst classes = computed(() => [\n ns.b(),\n ns.m(`padding-${props.padding}`),\n ns.is('raised', props.raised),\n ns.is('interactive', props.interactive),\n])\n</script>\n\n<template>\n <component :is=\"as\" :class=\"classes\">\n <header v-if=\"hasHeader\" :class=\"ns.e('header')\">\n <div :class=\"ns.e('heading')\">\n <slot name=\"header\">\n <div v-if=\"title\" :class=\"ns.e('title')\">{{ title }}</div>\n <div v-if=\"description\" :class=\"ns.e('description')\">{{ description }}</div>\n </slot>\n </div>\n <div v-if=\"slots.extra\" :class=\"ns.e('extra')\">\n <slot name=\"extra\" />\n </div>\n </header>\n <div v-if=\"slots.default\" :class=\"ns.e('body')\">\n <slot />\n </div>\n <footer v-if=\"slots.footer\" :class=\"ns.e('footer')\">\n <slot name=\"footer\" />\n </footer>\n </component>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"card.js","names":["_sfc_main"],"sources":["../../../src/components/card/card.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { useNamespace } from '../../utils/namespace'\nimport type { CardProps, CardSlots } from './card'\n\ndefineOptions({ name: 'DouCard' })\n\nconst props = withDefaults(defineProps<CardProps>(), {\n padding: 'md',\n raised: false,\n interactive: false,\n as: 'div',\n})\nconst slots = defineSlots<CardSlots>()\n\nconst ns = useNamespace('card')\n\nconst hasHeader = computed(\n () => !!(slots.header || slots.extra || props.title || props.description),\n)\n\n// A button may only hold phrasing content: inside one the parts are spans.\nconst inButton = computed(() => props.as === 'button')\nconst part = (tag: string) => (inButton.value ? 'span' : tag)\n\nconst classes = computed(() => [\n ns.b(),\n ns.m(`padding-${props.padding}`),\n ns.is('raised', props.raised),\n ns.is('interactive', props.interactive || inButton.value),\n])\n</script>\n\n<template>\n <component :is=\"as\" :class=\"classes\" :type=\"inButton ? 'button' : undefined\">\n <component :is=\"part('header')\" v-if=\"hasHeader\" :class=\"ns.e('header')\">\n <component :is=\"part('div')\" :class=\"ns.e('heading')\">\n <slot name=\"header\">\n <component :is=\"part('div')\" v-if=\"title\" :class=\"ns.e('title')\">{{ title }}</component>\n <component :is=\"part('div')\" v-if=\"description\" :class=\"ns.e('description')\">\n {{ description }}\n </component>\n </slot>\n </component>\n <component :is=\"part('div')\" v-if=\"slots.extra\" :class=\"ns.e('extra')\">\n <slot name=\"extra\" />\n </component>\n </component>\n <component :is=\"part('div')\" v-if=\"slots.default\" :class=\"ns.e('body')\">\n <slot />\n </component>\n <component :is=\"part('footer')\" v-if=\"slots.footer\" :class=\"ns.e('footer')\">\n <slot name=\"footer\" />\n </component>\n </component>\n</template>\n"],"mappings":""}
@@ -1,5 +1,5 @@
1
1
  import { useNamespace } from "../../utils/namespace.js";
2
- import { computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, defineComponent, normalizeClass, openBlock, renderSlot, resolveDynamicComponent, toDisplayString, unref, useSlots, withCtx } from "vue";
2
+ import { computed, createBlock, createCommentVNode, createTextVNode, defineComponent, normalizeClass, openBlock, renderSlot, resolveDynamicComponent, toDisplayString, unref, useSlots, withCtx } from "vue";
3
3
  // src/components/card/card.vue?vue&type=script&setup=true&lang.ts
4
4
  var card_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
5
5
  name: "DouCard",
@@ -23,39 +23,65 @@ var card_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineCompo
23
23
  const slots = useSlots();
24
24
  const ns = useNamespace("card");
25
25
  const hasHeader = computed(() => !!(slots.header || slots.extra || props.title || props.description));
26
+ const inButton = computed(() => props.as === "button");
27
+ const part = (tag) => inButton.value ? "span" : tag;
26
28
  const classes = computed(() => [
27
29
  ns.b(),
28
30
  ns.m(`padding-${props.padding}`),
29
31
  ns.is("raised", props.raised),
30
- ns.is("interactive", props.interactive)
32
+ ns.is("interactive", props.interactive || inButton.value)
31
33
  ]);
32
34
  return (_ctx, _cache) => {
33
- return openBlock(), createBlock(resolveDynamicComponent(__props.as), { class: normalizeClass(classes.value) }, {
35
+ return openBlock(), createBlock(resolveDynamicComponent(__props.as), {
36
+ class: normalizeClass(classes.value),
37
+ type: inButton.value ? "button" : void 0
38
+ }, {
34
39
  default: withCtx(() => [
35
- hasHeader.value ? (openBlock(), createElementBlock("header", {
40
+ hasHeader.value ? (openBlock(), createBlock(resolveDynamicComponent(part("header")), {
36
41
  key: 0,
37
42
  class: normalizeClass(unref(ns).e("header"))
38
- }, [createElementVNode("div", { class: normalizeClass(unref(ns).e("heading")) }, [renderSlot(_ctx.$slots, "header", {}, () => [__props.title ? (openBlock(), createElementBlock("div", {
39
- key: 0,
40
- class: normalizeClass(unref(ns).e("title"))
41
- }, toDisplayString(__props.title), 3)) : createCommentVNode("", true), __props.description ? (openBlock(), createElementBlock("div", {
42
- key: 1,
43
- class: normalizeClass(unref(ns).e("description"))
44
- }, toDisplayString(__props.description), 3)) : createCommentVNode("", true)])], 2), slots.extra ? (openBlock(), createElementBlock("div", {
45
- key: 0,
46
- class: normalizeClass(unref(ns).e("extra"))
47
- }, [renderSlot(_ctx.$slots, "extra")], 2)) : createCommentVNode("", true)], 2)) : createCommentVNode("", true),
48
- slots.default ? (openBlock(), createElementBlock("div", {
43
+ }, {
44
+ default: withCtx(() => [(openBlock(), createBlock(resolveDynamicComponent(part("div")), { class: normalizeClass(unref(ns).e("heading")) }, {
45
+ default: withCtx(() => [renderSlot(_ctx.$slots, "header", {}, () => [__props.title ? (openBlock(), createBlock(resolveDynamicComponent(part("div")), {
46
+ key: 0,
47
+ class: normalizeClass(unref(ns).e("title"))
48
+ }, {
49
+ default: withCtx(() => [createTextVNode(toDisplayString(__props.title), 1)]),
50
+ _: 1
51
+ }, 8, ["class"])) : createCommentVNode("", true), __props.description ? (openBlock(), createBlock(resolveDynamicComponent(part("div")), {
52
+ key: 1,
53
+ class: normalizeClass(unref(ns).e("description"))
54
+ }, {
55
+ default: withCtx(() => [createTextVNode(toDisplayString(__props.description), 1)]),
56
+ _: 1
57
+ }, 8, ["class"])) : createCommentVNode("", true)])]),
58
+ _: 3
59
+ }, 8, ["class"])), slots.extra ? (openBlock(), createBlock(resolveDynamicComponent(part("div")), {
60
+ key: 0,
61
+ class: normalizeClass(unref(ns).e("extra"))
62
+ }, {
63
+ default: withCtx(() => [renderSlot(_ctx.$slots, "extra")]),
64
+ _: 3
65
+ }, 8, ["class"])) : createCommentVNode("", true)]),
66
+ _: 3
67
+ }, 8, ["class"])) : createCommentVNode("", true),
68
+ slots.default ? (openBlock(), createBlock(resolveDynamicComponent(part("div")), {
49
69
  key: 1,
50
70
  class: normalizeClass(unref(ns).e("body"))
51
- }, [renderSlot(_ctx.$slots, "default")], 2)) : createCommentVNode("", true),
52
- slots.footer ? (openBlock(), createElementBlock("footer", {
71
+ }, {
72
+ default: withCtx(() => [renderSlot(_ctx.$slots, "default")]),
73
+ _: 3
74
+ }, 8, ["class"])) : createCommentVNode("", true),
75
+ slots.footer ? (openBlock(), createBlock(resolveDynamicComponent(part("footer")), {
53
76
  key: 2,
54
77
  class: normalizeClass(unref(ns).e("footer"))
55
- }, [renderSlot(_ctx.$slots, "footer")], 2)) : createCommentVNode("", true)
78
+ }, {
79
+ default: withCtx(() => [renderSlot(_ctx.$slots, "footer")]),
80
+ _: 3
81
+ }, 8, ["class"])) : createCommentVNode("", true)
56
82
  ]),
57
83
  _: 3
58
- }, 8, ["class"]);
84
+ }, 8, ["class", "type"]);
59
85
  };
60
86
  }
61
87
  });
@@ -1 +1 @@
1
- {"version":3,"file":"card.vue_vue_type_script_setup_true_lang.js","names":["_useSlots","_openBlock","_createBlock","_resolveDynamicComponent","_normalizeClass","_withCtx","_createElementBlock","_unref","_createElementVNode","_renderSlot","_toDisplayString","_createCommentVNode"],"sources":["../../../src/components/card/card.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { useNamespace } from '../../utils/namespace'\nimport type { CardProps, CardSlots } from './card'\n\ndefineOptions({ name: 'DouCard' })\n\nconst props = withDefaults(defineProps<CardProps>(), {\n padding: 'md',\n raised: false,\n interactive: false,\n as: 'div',\n})\nconst slots = defineSlots<CardSlots>()\n\nconst ns = useNamespace('card')\n\nconst hasHeader = computed(\n () => !!(slots.header || slots.extra || props.title || props.description),\n)\n\nconst classes = computed(() => [\n ns.b(),\n ns.m(`padding-${props.padding}`),\n ns.is('raised', props.raised),\n ns.is('interactive', props.interactive),\n])\n</script>\n\n<template>\n <component :is=\"as\" :class=\"classes\">\n <header v-if=\"hasHeader\" :class=\"ns.e('header')\">\n <div :class=\"ns.e('heading')\">\n <slot name=\"header\">\n <div v-if=\"title\" :class=\"ns.e('title')\">{{ title }}</div>\n <div v-if=\"description\" :class=\"ns.e('description')\">{{ description }}</div>\n </slot>\n </div>\n <div v-if=\"slots.extra\" :class=\"ns.e('extra')\">\n <slot name=\"extra\" />\n </div>\n </header>\n <div v-if=\"slots.default\" :class=\"ns.e('body')\">\n <slot />\n </div>\n <footer v-if=\"slots.footer\" :class=\"ns.e('footer')\">\n <slot name=\"footer\" />\n </footer>\n </component>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;EAOA,MAAM,QAAQ;EAMd,MAAM,QAAQA,SAAA;EAEd,MAAM,KAAK,aAAa,MAAM;EAE9B,MAAM,YAAY,eACV,CAAC,EAAE,MAAM,UAAU,MAAM,SAAS,MAAM,SAAS,MAAM,YAC/D;EAEA,MAAM,UAAU,eAAe;GAC7B,GAAG,EAAE;GACL,GAAG,EAAE,WAAW,MAAM,SAAS;GAC/B,GAAG,GAAG,UAAU,MAAM,MAAM;GAC5B,GAAG,GAAG,eAAe,MAAM,WAAW;EACxC,CAAC;;GAIC,OAAAC,UAAA,GAAAC,YAkBYC,wBAlBI,QAAA,EAAE,GAAA,EAAG,OAAKC,eAAE,QAAA,KAAO,E;IACjC,SAAAC,cAUS;KAVK,UAAA,SAAdJ,UAAA,GAAAK,mBAUS,UAAA;;MAViB,OAAKF,eAAEG,MAAA,EAAA,CAAE,CAAC,EAAC,QAAA,CAAA;K,IACnCC,mBAKM,OAAA,EALA,OAAKJ,eAAEG,MAAA,EAAA,CAAE,CAAC,EAAC,SAAA,CAAA,E,IACfE,WAGO,KAAA,QAAA,UAAA,CAAA,SAAA,CAFM,QAAA,SAAXR,UAAA,GAAAK,mBAA0D,OAAA;;MAAvC,OAAKF,eAAEG,MAAA,EAAA,CAAE,CAAC,EAAC,OAAA,CAAA;KAAc,GAAAG,gBAAA,QAAA,KAAK,GAAA,CAAA,K,8BACtC,QAAA,eAAXT,UAAA,GAAAK,mBAA4E,OAAA;;MAAnD,OAAKF,eAAEG,MAAA,EAAA,CAAE,CAAC,EAAC,aAAA,CAAA;KAAoB,GAAAG,gBAAA,QAAA,WAAW,GAAA,CAAA,K,qCAG5D,MAAM,SAAjBT,UAAA,GAAAK,mBAEM,OAAA;;MAFmB,OAAKF,eAAEG,MAAA,EAAA,CAAE,CAAC,EAAC,OAAA,CAAA;K,IAClCE,WAAqB,KAAA,QAAA,OAAA,C;KAGd,MAAM,WAAjBR,UAAA,GAAAK,mBAEM,OAAA;;MAFqB,OAAKF,eAAEG,MAAA,EAAA,CAAE,CAAC,EAAC,MAAA,CAAA;K,IACpCE,WAAQ,KAAA,QAAA,SAAA,C;KAEI,MAAM,UAApBR,UAAA,GAAAK,mBAES,UAAA;;MAFoB,OAAKF,eAAEG,MAAA,EAAA,CAAE,CAAC,EAAC,QAAA,CAAA;K,IACtCE,WAAsB,KAAA,QAAA,QAAA,C"}
1
+ {"version":3,"file":"card.vue_vue_type_script_setup_true_lang.js","names":["_useSlots","_openBlock","_createBlock","_resolveDynamicComponent","_normalizeClass","_withCtx","_unref","_renderSlot","_createTextVNode","_toDisplayString","_createCommentVNode"],"sources":["../../../src/components/card/card.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { useNamespace } from '../../utils/namespace'\nimport type { CardProps, CardSlots } from './card'\n\ndefineOptions({ name: 'DouCard' })\n\nconst props = withDefaults(defineProps<CardProps>(), {\n padding: 'md',\n raised: false,\n interactive: false,\n as: 'div',\n})\nconst slots = defineSlots<CardSlots>()\n\nconst ns = useNamespace('card')\n\nconst hasHeader = computed(\n () => !!(slots.header || slots.extra || props.title || props.description),\n)\n\n// A button may only hold phrasing content: inside one the parts are spans.\nconst inButton = computed(() => props.as === 'button')\nconst part = (tag: string) => (inButton.value ? 'span' : tag)\n\nconst classes = computed(() => [\n ns.b(),\n ns.m(`padding-${props.padding}`),\n ns.is('raised', props.raised),\n ns.is('interactive', props.interactive || inButton.value),\n])\n</script>\n\n<template>\n <component :is=\"as\" :class=\"classes\" :type=\"inButton ? 'button' : undefined\">\n <component :is=\"part('header')\" v-if=\"hasHeader\" :class=\"ns.e('header')\">\n <component :is=\"part('div')\" :class=\"ns.e('heading')\">\n <slot name=\"header\">\n <component :is=\"part('div')\" v-if=\"title\" :class=\"ns.e('title')\">{{ title }}</component>\n <component :is=\"part('div')\" v-if=\"description\" :class=\"ns.e('description')\">\n {{ description }}\n </component>\n </slot>\n </component>\n <component :is=\"part('div')\" v-if=\"slots.extra\" :class=\"ns.e('extra')\">\n <slot name=\"extra\" />\n </component>\n </component>\n <component :is=\"part('div')\" v-if=\"slots.default\" :class=\"ns.e('body')\">\n <slot />\n </component>\n <component :is=\"part('footer')\" v-if=\"slots.footer\" :class=\"ns.e('footer')\">\n <slot name=\"footer\" />\n </component>\n </component>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;EAOA,MAAM,QAAQ;EAMd,MAAM,QAAQA,SAAA;EAEd,MAAM,KAAK,aAAa,MAAM;EAE9B,MAAM,YAAY,eACV,CAAC,EAAE,MAAM,UAAU,MAAM,SAAS,MAAM,SAAS,MAAM,YAC/D;EAGA,MAAM,WAAW,eAAe,MAAM,OAAO,QAAQ;EACrD,MAAM,QAAQ,QAAiB,SAAS,QAAQ,SAAS;EAEzD,MAAM,UAAU,eAAe;GAC7B,GAAG,EAAE;GACL,GAAG,EAAE,WAAW,MAAM,SAAS;GAC/B,GAAG,GAAG,UAAU,MAAM,MAAM;GAC5B,GAAG,GAAG,eAAe,MAAM,eAAe,SAAS,KAAK;EAC1D,CAAC;;GAIC,OAAAC,UAAA,GAAAC,YAoBYC,wBApBI,QAAA,EAAE,GAAA;IAAG,OAAKC,eAAE,QAAA,KAAO;IAAG,MAAM,SAAA,QAAQ,WAAc,KAAA;;IAChE,SAAAC,cAYY;KAZ0B,UAAA,SAAtCJ,UAAA,GAAAC,YAYYC,wBAZI,KAAI,QAAA,CAAA,GAAA;;MAA8B,OAAKC,eAAEE,MAAA,EAAA,CAAE,CAAC,EAAC,QAAA,CAAA;;MAC3D,SAAAD,cAOY,EAPZJ,UAAA,GAAAC,YAOYC,wBAPI,KAAI,KAAA,CAAA,GAAA,EAAU,OAAKC,eAAEE,MAAA,EAAA,CAAE,CAAC,EAAC,SAAA,CAAA,E;OACvC,SAAAD,cAKO,CALPE,WAKO,KAAA,QAAA,UAAA,CAAA,SAAA,CAJ8B,QAAA,SAAnCN,UAAA,GAAAC,YAAwFC,wBAAxE,KAAI,KAAA,CAAA,GAAA;;QAAuB,OAAKC,eAAEE,MAAA,EAAA,CAAE,CAAC,EAAC,OAAA,CAAA;;QAAW,SAAAD,cAAW,CAARG,gBAAAC,gBAAA,QAAA,KAAK,GAAA,CAAA,C;;O,kDACtC,QAAA,eAAnCR,UAAA,GAAAC,YAEYC,wBAFI,KAAI,KAAA,CAAA,GAAA;;QAA6B,OAAKC,eAAEE,MAAA,EAAA,CAAE,CAAC,EAAC,aAAA,CAAA;;QAC1D,SAAAD,cAAiB,CAAdG,gBAAAC,gBAAA,QAAA,WAAW,GAAA,CAAA,C;;;;M,mBAIe,MAAM,SAAzCR,UAAA,GAAAC,YAEYC,wBAFI,KAAI,KAAA,CAAA,GAAA;;OAA6B,OAAKC,eAAEE,MAAA,EAAA,CAAE,CAAC,EAAC,OAAA,CAAA;;OAC1D,SAAAD,cAAqB,CAArBE,WAAqB,KAAA,QAAA,OAAA,C;;;;;KAGU,MAAM,WAAzCN,UAAA,GAAAC,YAEYC,wBAFI,KAAI,KAAA,CAAA,GAAA;;MAA+B,OAAKC,eAAEE,MAAA,EAAA,CAAE,CAAC,EAAC,MAAA,CAAA;;MAC5D,SAAAD,cAAQ,CAARE,WAAQ,KAAA,QAAA,SAAA,C;;;KAE4B,MAAM,UAA5CN,UAAA,GAAAC,YAEYC,wBAFI,KAAI,QAAA,CAAA,GAAA;;MAAiC,OAAKC,eAAEE,MAAA,EAAA,CAAE,CAAC,EAAC,QAAA,CAAA;;MAC9D,SAAAD,cAAsB,CAAtBE,WAAsB,KAAA,QAAA,QAAA,C"}
@@ -1 +1 @@
1
- {"version":3,"file":"chat-confirm.js","names":["_sfc_main"],"sources":["../../../src/components/chat-confirm/chat-confirm.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { CheckIcon, CloseIcon, ShieldIcon, UndoIcon } from '@dou-ui/icons'\nimport { computed, nextTick, ref, useId, watch } from 'vue'\nimport { useNamespace } from '../../utils/namespace'\nimport { useStatusCheck } from '../../utils/status-check'\nimport { DouButton } from '../button'\nimport { useLocale } from '../config-provider/use-config'\nimport type { ChatConfirmEmits, ChatConfirmProps, ChatConfirmSlots } from './chat-confirm'\n\ndefineOptions({ name: 'DouChatConfirm' })\n\nconst props = withDefaults(defineProps<ChatConfirmProps>(), {\n status: 'waiting',\n allowAlways: false,\n tone: 'neutral',\n})\nconst emit = defineEmits<ChatConfirmEmits>()\nconst slots = defineSlots<ChatConfirmSlots>()\n\nconst ns = useNamespace('chat-confirm')\nconst { t } = useLocale()\nconst id = useId()\n\nconst hasTitle = computed(() => !!props.title || !!slots.title)\nconst waiting = computed(() => props.status === 'waiting')\n// How each answered or withdrawn request reads once it has collapsed.\nconst outcomes = {\n approved: { icon: CheckIcon, text: 'chat.approved' },\n denied: { icon: CloseIcon, text: 'chat.denied' },\n withdrawn: { icon: UndoIcon, text: 'chat.withdrawn' },\n} as const\nconst outcome = computed(() =>\n Object.hasOwn(outcomes, props.status)\n ? outcomes[props.status as keyof typeof outcomes]\n : undefined,\n)\n\n// Answering or withdrawing removes the buttons; if focus was on one, keep it\n// on the card instead of losing it to the page. The watcher runs before the\n// DOM updates, while the focused button is still there to find.\nconst root = ref<HTMLElement>()\nwatch(\n () => props.status,\n (now, before) => {\n if (before !== 'waiting' || now === 'waiting') return\n if (!root.value?.contains(document.activeElement)) return\n void nextTick(() => root.value?.focus({ preventScroll: true }))\n },\n)\n\nconst statuses = ['waiting', 'approved', 'denied', 'withdrawn']\nuseStatusCheck('DouChatConfirm', () => [props.status], statuses, { pending: 'waiting' })\n</script>\n\n<template>\n <div\n ref=\"root\"\n :class=\"[ns.b(), ns.m(tone), ns.is(status)]\"\n role=\"group\"\n tabindex=\"-1\"\n :aria-labelledby=\"hasTitle ? `${id}-title` : undefined\"\n >\n <div :class=\"ns.e('header')\">\n <span :class=\"ns.e('icon')\" aria-hidden=\"true\">\n <slot name=\"icon\"><ShieldIcon /></slot>\n </span>\n <div :class=\"ns.e('text')\">\n <div v-if=\"hasTitle\" :id=\"`${id}-title`\" :class=\"ns.e('title')\">\n <slot name=\"title\">{{ title }}</slot>\n </div>\n <div v-if=\"description\" :class=\"ns.e('description')\">{{ description }}</div>\n </div>\n <!-- always there, so screen readers announce the outcome when it appears -->\n <span :class=\"ns.e('result')\" role=\"status\">\n <template v-if=\"outcome\">\n <component :is=\"outcome.icon\" aria-hidden=\"true\" />\n {{ t(outcome.text) }}\n </template>\n </span>\n </div>\n <div v-if=\"slots.default\" :class=\"ns.e('detail')\"><slot /></div>\n <div v-if=\"waiting\" :class=\"ns.e('actions')\">\n <DouButton size=\"sm\" variant=\"outline\" @click=\"emit('decide', 'deny')\">\n {{ denyText ?? t('chat.deny') }}\n </DouButton>\n <DouButton v-if=\"allowAlways\" size=\"sm\" variant=\"outline\" @click=\"emit('decide', 'always')\">\n {{ t('chat.allowAlways') }}\n </DouButton>\n <DouButton\n size=\"sm\"\n :tone=\"tone === 'danger' ? 'danger' : 'neutral'\"\n @click=\"emit('decide', 'approve')\"\n >\n {{ approveText ?? t('chat.approve') }}\n </DouButton>\n </div>\n </div>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"chat-confirm.js","names":["_sfc_main"],"sources":["../../../src/components/chat-confirm/chat-confirm.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { CheckIcon, CloseIcon, ShieldIcon, UndoIcon } from '@dou-ui/icons'\nimport { computed, nextTick, ref, useId, watch } from 'vue'\nimport { useNamespace } from '../../utils/namespace'\nimport { useStatusCheck } from '../../utils/status-check'\nimport { DouButton } from '../button'\nimport { useLocale } from '../config-provider/use-config'\nimport type { ChatConfirmEmits, ChatConfirmProps, ChatConfirmSlots } from './chat-confirm'\n\ndefineOptions({ name: 'DouChatConfirm' })\n\nconst props = withDefaults(defineProps<ChatConfirmProps>(), {\n status: 'waiting',\n allowAlways: false,\n tone: 'neutral',\n})\nconst emit = defineEmits<ChatConfirmEmits>()\nconst slots = defineSlots<ChatConfirmSlots>()\n\nconst ns = useNamespace('chat-confirm')\nconst { t } = useLocale()\nconst id = useId()\n\nconst waiting = computed(() => props.status === 'waiting')\n// How each answered or withdrawn request reads once it has collapsed.\nconst outcomes = {\n approved: { icon: CheckIcon, text: 'chat.approved' },\n denied: { icon: CloseIcon, text: 'chat.denied' },\n withdrawn: { icon: UndoIcon, text: 'chat.withdrawn' },\n} as const\nconst outcome = computed(() =>\n Object.hasOwn(outcomes, props.status)\n ? outcomes[props.status as keyof typeof outcomes]\n : undefined,\n)\n\n// Answering or withdrawing removes the buttons; if focus was on one, keep it\n// on the card instead of losing it to the page. The watcher runs before the\n// DOM updates, while the focused button is still there to find.\nconst root = ref<HTMLElement>()\nwatch(\n () => props.status,\n (now, before) => {\n if (before !== 'waiting' || now === 'waiting') return\n if (!root.value?.contains(document.activeElement)) return\n void nextTick(() => root.value?.focus({ preventScroll: true }))\n },\n)\n\nconst statuses = ['waiting', 'approved', 'denied', 'withdrawn']\nuseStatusCheck('DouChatConfirm', () => [props.status], statuses, { pending: 'waiting' })\n</script>\n\n<template>\n <div\n ref=\"root\"\n :class=\"[ns.b(), ns.m(tone), ns.is(status)]\"\n role=\"group\"\n tabindex=\"-1\"\n :aria-labelledby=\"title || slots.title ? `${id}-title` : undefined\"\n >\n <div :class=\"ns.e('header')\">\n <span :class=\"ns.e('icon')\" aria-hidden=\"true\">\n <slot name=\"icon\"><ShieldIcon /></slot>\n </span>\n <div :class=\"ns.e('text')\">\n <div v-if=\"title || slots.title\" :id=\"`${id}-title`\" :class=\"ns.e('title')\">\n <slot name=\"title\">{{ title }}</slot>\n </div>\n <div v-if=\"description\" :class=\"ns.e('description')\">{{ description }}</div>\n </div>\n <!-- always there, so screen readers announce the outcome when it appears -->\n <span :class=\"ns.e('result')\" role=\"status\">\n <template v-if=\"outcome\">\n <component :is=\"outcome.icon\" aria-hidden=\"true\" />\n {{ t(outcome.text) }}\n </template>\n </span>\n </div>\n <div v-if=\"slots.default\" :class=\"ns.e('detail')\"><slot /></div>\n <div v-if=\"waiting\" :class=\"ns.e('actions')\">\n <DouButton size=\"sm\" variant=\"outline\" @click=\"emit('decide', 'deny')\">\n {{ denyText ?? t('chat.deny') }}\n </DouButton>\n <DouButton v-if=\"allowAlways\" size=\"sm\" variant=\"outline\" @click=\"emit('decide', 'always')\">\n {{ t('chat.allowAlways') }}\n </DouButton>\n <DouButton\n size=\"sm\"\n :tone=\"tone === 'danger' ? 'danger' : 'neutral'\"\n @click=\"emit('decide', 'approve')\"\n >\n {{ approveText ?? t('chat.approve') }}\n </DouButton>\n </div>\n </div>\n</template>\n"],"mappings":""}
@@ -30,7 +30,6 @@ var chat_confirm_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ def
30
30
  const ns = useNamespace("chat-confirm");
31
31
  const { t } = useLocale();
32
32
  const id = useId();
33
- const hasTitle = computed(() => !!props.title || !!slots.title);
34
33
  const waiting = computed(() => props.status === "waiting");
35
34
  const outcomes = {
36
35
  approved: {
@@ -70,14 +69,14 @@ var chat_confirm_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ def
70
69
  ]),
71
70
  role: "group",
72
71
  tabindex: "-1",
73
- "aria-labelledby": hasTitle.value ? `${unref(id)}-title` : void 0
72
+ "aria-labelledby": __props.title || slots.title ? `${unref(id)}-title` : void 0
74
73
  }, [
75
74
  createElementVNode("div", { class: normalizeClass(unref(ns).e("header")) }, [
76
75
  createElementVNode("span", {
77
76
  class: normalizeClass(unref(ns).e("icon")),
78
77
  "aria-hidden": "true"
79
78
  }, [renderSlot(_ctx.$slots, "icon", {}, () => [createVNode(unref(ShieldIcon))])], 2),
80
- createElementVNode("div", { class: normalizeClass(unref(ns).e("text")) }, [hasTitle.value ? (openBlock(), createElementBlock("div", {
79
+ createElementVNode("div", { class: normalizeClass(unref(ns).e("text")) }, [__props.title || slots.title ? (openBlock(), createElementBlock("div", {
81
80
  key: 0,
82
81
  id: `${unref(id)}-title`,
83
82
  class: normalizeClass(unref(ns).e("title"))
@@ -1 +1 @@
1
- {"version":3,"file":"chat-confirm.vue_vue_type_script_setup_true_lang.js","names":["_useSlots","_openBlock","_createElementBlock","_normalizeClass","_unref","_createElementVNode","_renderSlot","_createVNode","_createTextVNode","_toDisplayString","_createCommentVNode","_Fragment","_createBlock","_resolveDynamicComponent","_withCtx"],"sources":["../../../src/components/chat-confirm/chat-confirm.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { CheckIcon, CloseIcon, ShieldIcon, UndoIcon } from '@dou-ui/icons'\nimport { computed, nextTick, ref, useId, watch } from 'vue'\nimport { useNamespace } from '../../utils/namespace'\nimport { useStatusCheck } from '../../utils/status-check'\nimport { DouButton } from '../button'\nimport { useLocale } from '../config-provider/use-config'\nimport type { ChatConfirmEmits, ChatConfirmProps, ChatConfirmSlots } from './chat-confirm'\n\ndefineOptions({ name: 'DouChatConfirm' })\n\nconst props = withDefaults(defineProps<ChatConfirmProps>(), {\n status: 'waiting',\n allowAlways: false,\n tone: 'neutral',\n})\nconst emit = defineEmits<ChatConfirmEmits>()\nconst slots = defineSlots<ChatConfirmSlots>()\n\nconst ns = useNamespace('chat-confirm')\nconst { t } = useLocale()\nconst id = useId()\n\nconst hasTitle = computed(() => !!props.title || !!slots.title)\nconst waiting = computed(() => props.status === 'waiting')\n// How each answered or withdrawn request reads once it has collapsed.\nconst outcomes = {\n approved: { icon: CheckIcon, text: 'chat.approved' },\n denied: { icon: CloseIcon, text: 'chat.denied' },\n withdrawn: { icon: UndoIcon, text: 'chat.withdrawn' },\n} as const\nconst outcome = computed(() =>\n Object.hasOwn(outcomes, props.status)\n ? outcomes[props.status as keyof typeof outcomes]\n : undefined,\n)\n\n// Answering or withdrawing removes the buttons; if focus was on one, keep it\n// on the card instead of losing it to the page. The watcher runs before the\n// DOM updates, while the focused button is still there to find.\nconst root = ref<HTMLElement>()\nwatch(\n () => props.status,\n (now, before) => {\n if (before !== 'waiting' || now === 'waiting') return\n if (!root.value?.contains(document.activeElement)) return\n void nextTick(() => root.value?.focus({ preventScroll: true }))\n },\n)\n\nconst statuses = ['waiting', 'approved', 'denied', 'withdrawn']\nuseStatusCheck('DouChatConfirm', () => [props.status], statuses, { pending: 'waiting' })\n</script>\n\n<template>\n <div\n ref=\"root\"\n :class=\"[ns.b(), ns.m(tone), ns.is(status)]\"\n role=\"group\"\n tabindex=\"-1\"\n :aria-labelledby=\"hasTitle ? `${id}-title` : undefined\"\n >\n <div :class=\"ns.e('header')\">\n <span :class=\"ns.e('icon')\" aria-hidden=\"true\">\n <slot name=\"icon\"><ShieldIcon /></slot>\n </span>\n <div :class=\"ns.e('text')\">\n <div v-if=\"hasTitle\" :id=\"`${id}-title`\" :class=\"ns.e('title')\">\n <slot name=\"title\">{{ title }}</slot>\n </div>\n <div v-if=\"description\" :class=\"ns.e('description')\">{{ description }}</div>\n </div>\n <!-- always there, so screen readers announce the outcome when it appears -->\n <span :class=\"ns.e('result')\" role=\"status\">\n <template v-if=\"outcome\">\n <component :is=\"outcome.icon\" aria-hidden=\"true\" />\n {{ t(outcome.text) }}\n </template>\n </span>\n </div>\n <div v-if=\"slots.default\" :class=\"ns.e('detail')\"><slot /></div>\n <div v-if=\"waiting\" :class=\"ns.e('actions')\">\n <DouButton size=\"sm\" variant=\"outline\" @click=\"emit('decide', 'deny')\">\n {{ denyText ?? t('chat.deny') }}\n </DouButton>\n <DouButton v-if=\"allowAlways\" size=\"sm\" variant=\"outline\" @click=\"emit('decide', 'always')\">\n {{ t('chat.allowAlways') }}\n </DouButton>\n <DouButton\n size=\"sm\"\n :tone=\"tone === 'danger' ? 'danger' : 'neutral'\"\n @click=\"emit('decide', 'approve')\"\n >\n {{ approveText ?? t('chat.approve') }}\n </DouButton>\n </div>\n </div>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"chat-confirm.vue_vue_type_script_setup_true_lang.js","names":["_useSlots","_openBlock","_createElementBlock","_normalizeClass","_unref","_createElementVNode","_renderSlot","_createVNode","_createTextVNode","_toDisplayString","_createCommentVNode","_Fragment","_createBlock","_resolveDynamicComponent","_withCtx"],"sources":["../../../src/components/chat-confirm/chat-confirm.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { CheckIcon, CloseIcon, ShieldIcon, UndoIcon } from '@dou-ui/icons'\nimport { computed, nextTick, ref, useId, watch } from 'vue'\nimport { useNamespace } from '../../utils/namespace'\nimport { useStatusCheck } from '../../utils/status-check'\nimport { DouButton } from '../button'\nimport { useLocale } from '../config-provider/use-config'\nimport type { ChatConfirmEmits, ChatConfirmProps, ChatConfirmSlots } from './chat-confirm'\n\ndefineOptions({ name: 'DouChatConfirm' })\n\nconst props = withDefaults(defineProps<ChatConfirmProps>(), {\n status: 'waiting',\n allowAlways: false,\n tone: 'neutral',\n})\nconst emit = defineEmits<ChatConfirmEmits>()\nconst slots = defineSlots<ChatConfirmSlots>()\n\nconst ns = useNamespace('chat-confirm')\nconst { t } = useLocale()\nconst id = useId()\n\nconst waiting = computed(() => props.status === 'waiting')\n// How each answered or withdrawn request reads once it has collapsed.\nconst outcomes = {\n approved: { icon: CheckIcon, text: 'chat.approved' },\n denied: { icon: CloseIcon, text: 'chat.denied' },\n withdrawn: { icon: UndoIcon, text: 'chat.withdrawn' },\n} as const\nconst outcome = computed(() =>\n Object.hasOwn(outcomes, props.status)\n ? outcomes[props.status as keyof typeof outcomes]\n : undefined,\n)\n\n// Answering or withdrawing removes the buttons; if focus was on one, keep it\n// on the card instead of losing it to the page. The watcher runs before the\n// DOM updates, while the focused button is still there to find.\nconst root = ref<HTMLElement>()\nwatch(\n () => props.status,\n (now, before) => {\n if (before !== 'waiting' || now === 'waiting') return\n if (!root.value?.contains(document.activeElement)) return\n void nextTick(() => root.value?.focus({ preventScroll: true }))\n },\n)\n\nconst statuses = ['waiting', 'approved', 'denied', 'withdrawn']\nuseStatusCheck('DouChatConfirm', () => [props.status], statuses, { pending: 'waiting' })\n</script>\n\n<template>\n <div\n ref=\"root\"\n :class=\"[ns.b(), ns.m(tone), ns.is(status)]\"\n role=\"group\"\n tabindex=\"-1\"\n :aria-labelledby=\"title || slots.title ? `${id}-title` : undefined\"\n >\n <div :class=\"ns.e('header')\">\n <span :class=\"ns.e('icon')\" aria-hidden=\"true\">\n <slot name=\"icon\"><ShieldIcon /></slot>\n </span>\n <div :class=\"ns.e('text')\">\n <div v-if=\"title || slots.title\" :id=\"`${id}-title`\" :class=\"ns.e('title')\">\n <slot name=\"title\">{{ title }}</slot>\n </div>\n <div v-if=\"description\" :class=\"ns.e('description')\">{{ description }}</div>\n </div>\n <!-- always there, so screen readers announce the outcome when it appears -->\n <span :class=\"ns.e('result')\" role=\"status\">\n <template v-if=\"outcome\">\n <component :is=\"outcome.icon\" aria-hidden=\"true\" />\n {{ t(outcome.text) }}\n </template>\n </span>\n </div>\n <div v-if=\"slots.default\" :class=\"ns.e('detail')\"><slot /></div>\n <div v-if=\"waiting\" :class=\"ns.e('actions')\">\n <DouButton size=\"sm\" variant=\"outline\" @click=\"emit('decide', 'deny')\">\n {{ denyText ?? t('chat.deny') }}\n </DouButton>\n <DouButton v-if=\"allowAlways\" size=\"sm\" variant=\"outline\" @click=\"emit('decide', 'always')\">\n {{ t('chat.allowAlways') }}\n </DouButton>\n <DouButton\n size=\"sm\"\n :tone=\"tone === 'danger' ? 'danger' : 'neutral'\"\n @click=\"emit('decide', 'approve')\"\n >\n {{ approveText ?? t('chat.approve') }}\n </DouButton>\n </div>\n </div>\n</template>\n"],"mappings":"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"}
@@ -1,12 +1,29 @@
1
1
  // src/components/chat-context-meter/chat-context-meter.ts
2
+ var count = (n) => Number.isFinite(n) && n > 0 ? n : 0;
3
+ /**
4
+ * The numbers the meter shows for `used` and `total`, for a tooltip or
5
+ * details around it that agree with the ring: `percent` stays within 0–100
6
+ * and is 0 without a `total`.
7
+ */
8
+ function contextUsage(used, total) {
9
+ const u = count(used);
10
+ const all = count(total);
11
+ const share = all > 0 ? Math.min(u / all, 1) : 0;
12
+ return {
13
+ used: u,
14
+ total: all,
15
+ share,
16
+ percent: Math.round(share * 100)
17
+ };
18
+ }
2
19
  var trim = (n) => String(Number(n.toFixed(1)));
3
- /** `45200` → `45.2k`, `1200000` → `1.2M`. */
20
+ /** `45200` → `45.2k`, `1200000` → `1.2M`: how the meter reads its numbers, for tooltips around it. */
4
21
  function compactNumber(value) {
5
22
  const abs = Math.abs(value);
6
23
  if (abs >= 1e6) return `${trim(value / 1e6)}M`;
7
24
  if (abs >= 1e3) return `${trim(value / 1e3)}k`;
8
25
  return String(Math.round(value));
9
26
  }
10
- export { compactNumber };
27
+ export { compactNumber, contextUsage };
11
28
 
12
29
  //# sourceMappingURL=chat-context-meter.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"chat-context-meter.js","names":[],"sources":["../../../src/components/chat-context-meter/chat-context-meter.ts"],"sourcesContent":["export interface ChatContextMeterProps {\n /** Tokens used so far. */\n used?: number\n /** Tokens the context holds. */\n total?: number\n /** How numbers read in the tooltip. Defaults to a compact form, e.g. `45.2k`. */\n format?: (value: number) => string\n /** The share, from 0 to 1, from which the ring turns to the warning tone. */\n warnAt?: number\n /** The share from which it turns to the danger tone. */\n dangerAt?: number\n /** Show the percentage next to the ring. */\n showLabel?: boolean\n}\n\nconst trim = (n: number) => String(Number(n.toFixed(1)))\n\n/** `45200` → `45.2k`, `1200000` → `1.2M`. */\nexport function compactNumber(value: number): string {\n const abs = Math.abs(value)\n if (abs >= 1e6) return `${trim(value / 1e6)}M`\n if (abs >= 1e3) return `${trim(value / 1e3)}k`\n return String(Math.round(value))\n}\n"],"mappings":";AAeA,IAAM,QAAQ,MAAc,OAAO,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;;AAGvD,SAAgB,cAAc,OAAuB;CACnD,MAAM,MAAM,KAAK,IAAI,KAAK;CAC1B,IAAI,OAAO,KAAK,OAAO,GAAG,KAAK,QAAQ,GAAG,EAAE;CAC5C,IAAI,OAAO,KAAK,OAAO,GAAG,KAAK,QAAQ,GAAG,EAAE;CAC5C,OAAO,OAAO,KAAK,MAAM,KAAK,CAAC;AACjC"}
1
+ {"version":3,"file":"chat-context-meter.js","names":[],"sources":["../../../src/components/chat-context-meter/chat-context-meter.ts"],"sourcesContent":["/**\n * Only the ring: no tooltip, not focusable. A DouTooltip can wrap the ring\n * itself (give it `tabindex=\"0\"`); a popover or dropdown opened by a click\n * needs a button holding the ring, which a span can't stand in for. Name it\n * with `aria-label`.\n */\nexport interface ChatContextMeterProps {\n /** Tokens used so far. */\n used?: number\n /** Tokens the context holds. */\n total?: number\n /** The share, from 0 to 1, from which the ring turns to the warning tone. */\n warnAt?: number\n /** The share from which it turns to the danger tone. */\n dangerAt?: number\n /** Show the percentage next to the ring. */\n showLabel?: boolean\n}\n\nexport interface ContextUsage {\n /** Tokens used: a number below 0, or not a finite number, counts as 0. */\n used: number\n /** Tokens the context holds, the same way. */\n total: number\n /** How full, from 0 to 1, as the ring draws it. */\n share: number\n /** The share as a whole percent, as the ring's label shows it: never over 100. */\n percent: number\n}\n\nconst count = (n: number) => (Number.isFinite(n) && n > 0 ? n : 0)\n\n/**\n * The numbers the meter shows for `used` and `total`, for a tooltip or\n * details around it that agree with the ring: `percent` stays within 0–100\n * and is 0 without a `total`.\n */\nexport function contextUsage(used: number, total: number): ContextUsage {\n const u = count(used)\n const all = count(total)\n const share = all > 0 ? Math.min(u / all, 1) : 0\n return { used: u, total: all, share, percent: Math.round(share * 100) }\n}\n\nconst trim = (n: number) => String(Number(n.toFixed(1)))\n\n/** `45200` → `45.2k`, `1200000` → `1.2M`: how the meter reads its numbers, for tooltips around it. */\nexport function compactNumber(value: number): string {\n const abs = Math.abs(value)\n if (abs >= 1e6) return `${trim(value / 1e6)}M`\n if (abs >= 1e3) return `${trim(value / 1e3)}k`\n return String(Math.round(value))\n}\n"],"mappings":";AA8BA,IAAM,SAAS,MAAe,OAAO,SAAS,CAAC,KAAK,IAAI,IAAI,IAAI;;;;;;AAOhE,SAAgB,aAAa,MAAc,OAA6B;CACtE,MAAM,IAAI,MAAM,IAAI;CACpB,MAAM,MAAM,MAAM,KAAK;CACvB,MAAM,QAAQ,MAAM,IAAI,KAAK,IAAI,IAAI,KAAK,CAAC,IAAI;CAC/C,OAAO;EAAE,MAAM;EAAG,OAAO;EAAK;EAAO,SAAS,KAAK,MAAM,QAAQ,GAAG;CAAE;AACxE;AAEA,IAAM,QAAQ,MAAc,OAAO,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;;AAGvD,SAAgB,cAAc,OAAuB;CACnD,MAAM,MAAM,KAAK,IAAI,KAAK;CAC1B,IAAI,OAAO,KAAK,OAAO,GAAG,KAAK,QAAQ,GAAG,EAAE;CAC5C,IAAI,OAAO,KAAK,OAAO,GAAG,KAAK,QAAQ,GAAG,EAAE;CAC5C,OAAO,OAAO,KAAK,MAAM,KAAK,CAAC;AACjC"}
@@ -1,8 +1,8 @@
1
1
  import { useNamespace } from "../../utils/namespace.js";
2
2
  import { useLocale } from "../config-provider/use-config.js";
3
- import { DouTooltip } from "../tooltip/index.js";
4
- import { compactNumber } from "./chat-context-meter.js";
5
- import { computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, defineComponent, mergeProps, normalizeClass, openBlock, toDisplayString, unref, withCtx } from "vue";
3
+ import { devWarn } from "../../utils/status-check.js";
4
+ import { compactNumber, contextUsage } from "./chat-context-meter.js";
5
+ import { computed, createCommentVNode, createElementBlock, createElementVNode, defineComponent, normalizeClass, onMounted, openBlock, toDisplayString, unref, useTemplateRef } from "vue";
6
6
  // src/components/chat-context-meter/chat-context-meter.vue?vue&type=script&setup=true&lang.ts
7
7
  var _hoisted_1 = [
8
8
  "aria-label",
@@ -12,12 +12,10 @@ var _hoisted_1 = [
12
12
  var _hoisted_2 = ["stroke-dasharray"];
13
13
  var chat_context_meter_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
14
14
  name: "DouChatContextMeter",
15
- inheritAttrs: false,
16
15
  __name: "chat-context-meter",
17
16
  props: {
18
17
  used: { default: 0 },
19
18
  total: { default: 0 },
20
- format: {},
21
19
  warnAt: { default: .8 },
22
20
  dangerAt: { default: .95 },
23
21
  showLabel: {
@@ -29,48 +27,51 @@ var chat_context_meter_vue_vue_type_script_setup_true_lang_default = /*@__PURE__
29
27
  const props = __props;
30
28
  const ns = useNamespace("chat-context-meter");
31
29
  const { t } = useLocale();
32
- const share = computed(() => props.total > 0 ? Math.min(Math.max(props.used / props.total, 0), 1) : 0);
33
- const percent = computed(() => Math.round(share.value * 100));
30
+ const usage = computed(() => contextUsage(props.used, props.total));
31
+ const share = computed(() => usage.value.share);
32
+ const percent = computed(() => usage.value.percent);
34
33
  const tone = computed(() => share.value >= props.dangerAt ? "danger" : share.value >= props.warnAt ? "warning" : "neutral");
35
- const fmt = (value) => (props.format ?? compactNumber)(value);
36
- const text = computed(() => t("chat.context", {
37
- used: fmt(props.used),
38
- total: fmt(props.total),
34
+ const valueText = computed(() => t("chat.context", {
35
+ used: compactNumber(usage.value.used),
36
+ total: compactNumber(usage.value.total),
39
37
  percent: percent.value
40
38
  }));
39
+ const root = useTemplateRef("root");
40
+ onMounted(() => {
41
+ if (process.env.NODE_ENV === "production" || !props.showLabel) return;
42
+ if (root.value?.parentElement?.closest(".dou-button.is-icon-only")) devWarn("[dou-ui] DouChatContextMeter: `showLabel` inside an icon-only button spills out of it, as the button sizes the ring as its icon. Put the ring in the button’s `leading` slot and the percentage as its text.");
43
+ });
41
44
  const CIRCUMFERENCE = 2 * Math.PI * 6;
42
45
  return (_ctx, _cache) => {
43
- return openBlock(), createBlock(unref(DouTooltip), { content: text.value }, {
44
- default: withCtx(() => [createElementVNode("span", mergeProps(_ctx.$attrs, {
45
- class: [unref(ns).b(), unref(ns).m(tone.value)],
46
- role: "meter",
47
- tabindex: "0",
48
- "aria-label": unref(t)("chat.contextLabel"),
49
- "aria-valuenow": percent.value,
50
- "aria-valuemin": "0",
51
- "aria-valuemax": "100",
52
- "aria-valuetext": text.value
53
- }), [(openBlock(), createElementBlock("svg", {
54
- class: normalizeClass(unref(ns).e("ring")),
55
- viewBox: "0 0 16 16",
56
- "aria-hidden": "true"
57
- }, [createElementVNode("circle", {
58
- class: normalizeClass(unref(ns).e("track")),
59
- cx: "8",
60
- cy: "8",
61
- r: "6"
62
- }, null, 2), createElementVNode("circle", {
63
- class: normalizeClass(unref(ns).e("bar")),
64
- cx: "8",
65
- cy: "8",
66
- r: "6",
67
- "stroke-dasharray": `${CIRCUMFERENCE * share.value} ${CIRCUMFERENCE}`
68
- }, null, 10, _hoisted_2)], 2)), __props.showLabel ? (openBlock(), createElementBlock("span", {
69
- key: 0,
70
- class: normalizeClass(unref(ns).e("label"))
71
- }, toDisplayString(percent.value) + "%", 3)) : createCommentVNode("", true)], 16, _hoisted_1)]),
72
- _: 1
73
- }, 8, ["content"]);
46
+ return openBlock(), createElementBlock("span", {
47
+ ref_key: "root",
48
+ ref: root,
49
+ class: normalizeClass([unref(ns).b(), unref(ns).m(tone.value)]),
50
+ role: "meter",
51
+ "aria-label": unref(t)("chat.contextLabel"),
52
+ "aria-valuenow": percent.value,
53
+ "aria-valuemin": "0",
54
+ "aria-valuemax": "100",
55
+ "aria-valuetext": valueText.value
56
+ }, [(openBlock(), createElementBlock("svg", {
57
+ class: normalizeClass(unref(ns).e("ring")),
58
+ viewBox: "0 0 16 16",
59
+ "aria-hidden": "true"
60
+ }, [createElementVNode("circle", {
61
+ class: normalizeClass(unref(ns).e("track")),
62
+ cx: "8",
63
+ cy: "8",
64
+ r: "6"
65
+ }, null, 2), createElementVNode("circle", {
66
+ class: normalizeClass(unref(ns).e("bar")),
67
+ cx: "8",
68
+ cy: "8",
69
+ r: "6",
70
+ "stroke-dasharray": `${CIRCUMFERENCE * share.value} ${CIRCUMFERENCE}`
71
+ }, null, 10, _hoisted_2)], 2)), __props.showLabel ? (openBlock(), createElementBlock("span", {
72
+ key: 0,
73
+ class: normalizeClass(unref(ns).e("label"))
74
+ }, toDisplayString(percent.value) + "%", 3)) : createCommentVNode("", true)], 10, _hoisted_1);
74
75
  };
75
76
  }
76
77
  });
@@ -1 +1 @@
1
- {"version":3,"file":"chat-context-meter.vue_vue_type_script_setup_true_lang.js","names":["$attrs","_openBlock","_createBlock","_unref","_withCtx","_createElementVNode","_mergeProps","_createElementBlock","_normalizeClass","_toDisplayString","_createCommentVNode"],"sources":["../../../src/components/chat-context-meter/chat-context-meter.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { useNamespace } from '../../utils/namespace'\nimport { useLocale } from '../config-provider/use-config'\nimport { DouTooltip } from '../tooltip'\nimport { compactNumber } from './chat-context-meter'\nimport type { ChatContextMeterProps } from './chat-context-meter'\n\ndefineOptions({ name: 'DouChatContextMeter', inheritAttrs: false })\n\nconst props = withDefaults(defineProps<ChatContextMeterProps>(), {\n used: 0,\n total: 0,\n warnAt: 0.8,\n dangerAt: 0.95,\n showLabel: false,\n})\n\nconst ns = useNamespace('chat-context-meter')\nconst { t } = useLocale()\n\nconst share = computed(() =>\n props.total > 0 ? Math.min(Math.max(props.used / props.total, 0), 1) : 0,\n)\nconst percent = computed(() => Math.round(share.value * 100))\nconst tone = computed(() =>\n share.value >= props.dangerAt ? 'danger' : share.value >= props.warnAt ? 'warning' : 'neutral',\n)\nconst fmt = (value: number) => (props.format ?? compactNumber)(value)\nconst text = computed(() =>\n t('chat.context', { used: fmt(props.used), total: fmt(props.total), percent: percent.value }),\n)\n\n// r = 6 on a 16 box; the circumference drives the dash\nconst CIRCUMFERENCE = 2 * Math.PI * 6\n</script>\n\n<template>\n <DouTooltip :content=\"text\">\n <span\n v-bind=\"$attrs\"\n :class=\"[ns.b(), ns.m(tone)]\"\n role=\"meter\"\n tabindex=\"0\"\n :aria-label=\"t('chat.contextLabel')\"\n :aria-valuenow=\"percent\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n :aria-valuetext=\"text\"\n >\n <svg :class=\"ns.e('ring')\" viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <circle :class=\"ns.e('track')\" cx=\"8\" cy=\"8\" r=\"6\" />\n <circle\n :class=\"ns.e('bar')\"\n cx=\"8\"\n cy=\"8\"\n r=\"6\"\n :stroke-dasharray=\"`${CIRCUMFERENCE * share} ${CIRCUMFERENCE}`\"\n />\n </svg>\n <span v-if=\"showLabel\" :class=\"ns.e('label')\">{{ percent }}%</span>\n </span>\n </DouTooltip>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;EAUA,MAAM,QAAQ;EAQd,MAAM,KAAK,aAAa,oBAAoB;EAC5C,MAAM,EAAE,MAAM,UAAU;EAExB,MAAM,QAAQ,eACZ,MAAM,QAAQ,IAAI,KAAK,IAAI,KAAK,IAAI,MAAM,OAAO,MAAM,OAAO,CAAC,GAAG,CAAC,IAAI,CACzE;EACA,MAAM,UAAU,eAAe,KAAK,MAAM,MAAM,QAAQ,GAAG,CAAC;EAC5D,MAAM,OAAO,eACX,MAAM,SAAS,MAAM,WAAW,WAAW,MAAM,SAAS,MAAM,SAAS,YAAY,SACvF;EACA,MAAM,OAAO,WAAmB,MAAM,UAAU,cAAA,CAAe,KAAK;EACpE,MAAM,OAAO,eACX,EAAE,gBAAgB;GAAE,MAAM,IAAI,MAAM,IAAI;GAAG,OAAO,IAAI,MAAM,KAAK;GAAG,SAAS,QAAQ;EAAM,CAAC,CAC9F;EAGA,MAAM,gBAAgB,IAAI,KAAK,KAAK;;GAIlC,OAAAC,UAAA,GAAAC,YAwBaC,MAAA,UAAA,GAAA,EAxBA,SAAS,KAAA,MAAI,GAAA;IACxB,SAAAC,cAsBO,CAtBPC,mBAsBO,QAtBPC,WACUN,KAqBH,QArBS;KACb,OAAK,CAAGG,MAAA,EAAA,CAAE,CAAC,EAAC,GAAIA,MAAA,EAAA,CAAE,CAAC,EAAE,KAAA,KAAI,CAAA;KAC1B,MAAK;KACL,UAAS;KACR,cAAYA,MAAA,CAAA,CAAC,CAAA,mBAAA;KACb,iBAAe,QAAA;KAChB,iBAAc;KACd,iBAAc;KACb,kBAAgB,KAAA;I,MAEjBF,UAAA,GAAAM,mBASM,OAAA;KATA,OAAKC,eAAEL,MAAA,EAAA,CAAE,CAAC,EAAC,MAAA,CAAA;KAAU,SAAQ;KAAY,eAAY;I,IACzDE,mBAAqD,UAAA;KAA5C,OAAKG,eAAEL,MAAA,EAAA,CAAE,CAAC,EAAC,OAAA,CAAA;KAAW,IAAG;KAAI,IAAG;KAAI,GAAE;I,aAC/CE,mBAME,UAAA;KALC,OAAKG,eAAEL,MAAA,EAAA,CAAE,CAAC,EAAC,KAAA,CAAA;KACZ,IAAG;KACH,IAAG;KACH,GAAE;KACD,oBAAgB,GAAK,gBAAgB,MAAA,MAAK,GAAI;I,gCAGvC,QAAA,aAAZF,UAAA,GAAAM,mBAAmE,QAAA;;KAA3C,OAAKC,eAAEL,MAAA,EAAA,CAAE,CAAC,EAAC,OAAA,CAAA;IAAc,GAAAM,gBAAA,QAAA,KAAO,IAAG,KAAC,CAAA,K"}
1
+ {"version":3,"file":"chat-context-meter.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createElementBlock","_normalizeClass","_unref","_createElementVNode","_toDisplayString","_createCommentVNode"],"sources":["../../../src/components/chat-context-meter/chat-context-meter.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, onMounted, useTemplateRef } from 'vue'\nimport { useNamespace } from '../../utils/namespace'\nimport { devWarn } from '../../utils/status-check'\nimport { useLocale } from '../config-provider/use-config'\nimport { compactNumber, contextUsage } from './chat-context-meter'\nimport type { ChatContextMeterProps } from './chat-context-meter'\n\ndefineOptions({ name: 'DouChatContextMeter' })\n\nconst props = withDefaults(defineProps<ChatContextMeterProps>(), {\n used: 0,\n total: 0,\n warnAt: 0.8,\n dangerAt: 0.95,\n showLabel: false,\n})\n\nconst ns = useNamespace('chat-context-meter')\nconst { t } = useLocale()\n\nconst usage = computed(() => contextUsage(props.used, props.total))\nconst share = computed(() => usage.value.share)\nconst percent = computed(() => usage.value.percent)\nconst tone = computed(() =>\n share.value >= props.dangerAt ? 'danger' : share.value >= props.warnAt ? 'warning' : 'neutral',\n)\n// what a screen reader hears for the value; the ring shows no numbers\nconst valueText = computed(() =>\n t('chat.context', {\n used: compactNumber(usage.value.used),\n total: compactNumber(usage.value.total),\n percent: percent.value,\n }),\n)\n\n// an icon-only button sizes the ring as its icon: the label would spill out of it\nconst root = useTemplateRef<HTMLElement>('root')\nonMounted(() => {\n if (process.env.NODE_ENV === 'production' || !props.showLabel) return\n if (root.value?.parentElement?.closest('.dou-button.is-icon-only'))\n devWarn(\n '[dou-ui] DouChatContextMeter: `showLabel` inside an icon-only button spills out of it, as the button sizes the ring as its icon. Put the ring in the button’s `leading` slot and the percentage as its text.',\n )\n})\n\n// r = 6 on a 16 box; the circumference drives the dash\nconst CIRCUMFERENCE = 2 * Math.PI * 6\n</script>\n\n<template>\n <!-- only the ring: a tooltip or popover goes around it, so it takes no focus of its own; an `aria-label` passed in replaces the default name -->\n <span\n ref=\"root\"\n :class=\"[ns.b(), ns.m(tone)]\"\n role=\"meter\"\n :aria-label=\"t('chat.contextLabel')\"\n :aria-valuenow=\"percent\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n :aria-valuetext=\"valueText\"\n >\n <svg :class=\"ns.e('ring')\" viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <circle :class=\"ns.e('track')\" cx=\"8\" cy=\"8\" r=\"6\" />\n <circle\n :class=\"ns.e('bar')\"\n cx=\"8\"\n cy=\"8\"\n r=\"6\"\n :stroke-dasharray=\"`${CIRCUMFERENCE * share} ${CIRCUMFERENCE}`\"\n />\n </svg>\n <span v-if=\"showLabel\" :class=\"ns.e('label')\">{{ percent }}%</span>\n </span>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;EAUA,MAAM,QAAQ;EAQd,MAAM,KAAK,aAAa,oBAAoB;EAC5C,MAAM,EAAE,MAAM,UAAU;EAExB,MAAM,QAAQ,eAAe,aAAa,MAAM,MAAM,MAAM,KAAK,CAAC;EAClE,MAAM,QAAQ,eAAe,MAAM,MAAM,KAAK;EAC9C,MAAM,UAAU,eAAe,MAAM,MAAM,OAAO;EAClD,MAAM,OAAO,eACX,MAAM,SAAS,MAAM,WAAW,WAAW,MAAM,SAAS,MAAM,SAAS,YAAY,SACvF;EAEA,MAAM,YAAY,eAChB,EAAE,gBAAgB;GAChB,MAAM,cAAc,MAAM,MAAM,IAAI;GACpC,OAAO,cAAc,MAAM,MAAM,KAAK;GACtC,SAAS,QAAQ;EACnB,CAAC,CACH;EAGA,MAAM,OAAO,eAA4B,MAAM;EAC/C,gBAAgB;GACd,IAAA,QAAA,IAAA,aAA6B,gBAAgB,CAAC,MAAM,WAAW;GAC/D,IAAI,KAAK,OAAO,eAAe,QAAQ,0BAA0B,GAC/D,QACE,8MACF;EACJ,CAAC;EAGD,MAAM,gBAAgB,IAAI,KAAK,KAAK;;GAKlC,OAAAA,UAAA,GAAAC,mBAqBO,QAAA;IApBD,SAAA;IAAJ,KAAI;IACH,OAAKC,eAAA,CAAGC,MAAA,EAAA,CAAE,CAAC,EAAC,GAAIA,MAAA,EAAA,CAAE,CAAC,EAAE,KAAA,KAAI,CAAA,CAAA;IAC1B,MAAK;IACJ,cAAYA,MAAA,CAAA,CAAC,CAAA,mBAAA;IACb,iBAAe,QAAA;IAChB,iBAAc;IACd,iBAAc;IACb,kBAAgB,UAAA;G,KAEjBH,UAAA,GAAAC,mBASM,OAAA;IATA,OAAKC,eAAEC,MAAA,EAAA,CAAE,CAAC,EAAC,MAAA,CAAA;IAAU,SAAQ;IAAY,eAAY;G,IACzDC,mBAAqD,UAAA;IAA5C,OAAKF,eAAEC,MAAA,EAAA,CAAE,CAAC,EAAC,OAAA,CAAA;IAAW,IAAG;IAAI,IAAG;IAAI,GAAE;G,aAC/CC,mBAME,UAAA;IALC,OAAKF,eAAEC,MAAA,EAAA,CAAE,CAAC,EAAC,KAAA,CAAA;IACZ,IAAG;IACH,IAAG;IACH,GAAE;IACD,oBAAgB,GAAK,gBAAgB,MAAA,MAAK,GAAI;G,gCAGvC,QAAA,aAAZH,UAAA,GAAAC,mBAAmE,QAAA;;IAA3C,OAAKC,eAAEC,MAAA,EAAA,CAAE,CAAC,EAAC,OAAA,CAAA;GAAc,GAAAE,gBAAA,QAAA,KAAO,IAAG,KAAC,CAAA,K"}
@@ -1 +1 @@
1
- {"version":3,"file":"chat-context-meter2.js","names":["_sfc_main"],"sources":["../../../src/components/chat-context-meter/chat-context-meter.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { useNamespace } from '../../utils/namespace'\nimport { useLocale } from '../config-provider/use-config'\nimport { DouTooltip } from '../tooltip'\nimport { compactNumber } from './chat-context-meter'\nimport type { ChatContextMeterProps } from './chat-context-meter'\n\ndefineOptions({ name: 'DouChatContextMeter', inheritAttrs: false })\n\nconst props = withDefaults(defineProps<ChatContextMeterProps>(), {\n used: 0,\n total: 0,\n warnAt: 0.8,\n dangerAt: 0.95,\n showLabel: false,\n})\n\nconst ns = useNamespace('chat-context-meter')\nconst { t } = useLocale()\n\nconst share = computed(() =>\n props.total > 0 ? Math.min(Math.max(props.used / props.total, 0), 1) : 0,\n)\nconst percent = computed(() => Math.round(share.value * 100))\nconst tone = computed(() =>\n share.value >= props.dangerAt ? 'danger' : share.value >= props.warnAt ? 'warning' : 'neutral',\n)\nconst fmt = (value: number) => (props.format ?? compactNumber)(value)\nconst text = computed(() =>\n t('chat.context', { used: fmt(props.used), total: fmt(props.total), percent: percent.value }),\n)\n\n// r = 6 on a 16 box; the circumference drives the dash\nconst CIRCUMFERENCE = 2 * Math.PI * 6\n</script>\n\n<template>\n <DouTooltip :content=\"text\">\n <span\n v-bind=\"$attrs\"\n :class=\"[ns.b(), ns.m(tone)]\"\n role=\"meter\"\n tabindex=\"0\"\n :aria-label=\"t('chat.contextLabel')\"\n :aria-valuenow=\"percent\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n :aria-valuetext=\"text\"\n >\n <svg :class=\"ns.e('ring')\" viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <circle :class=\"ns.e('track')\" cx=\"8\" cy=\"8\" r=\"6\" />\n <circle\n :class=\"ns.e('bar')\"\n cx=\"8\"\n cy=\"8\"\n r=\"6\"\n :stroke-dasharray=\"`${CIRCUMFERENCE * share} ${CIRCUMFERENCE}`\"\n />\n </svg>\n <span v-if=\"showLabel\" :class=\"ns.e('label')\">{{ percent }}%</span>\n </span>\n </DouTooltip>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"chat-context-meter2.js","names":["_sfc_main"],"sources":["../../../src/components/chat-context-meter/chat-context-meter.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, onMounted, useTemplateRef } from 'vue'\nimport { useNamespace } from '../../utils/namespace'\nimport { devWarn } from '../../utils/status-check'\nimport { useLocale } from '../config-provider/use-config'\nimport { compactNumber, contextUsage } from './chat-context-meter'\nimport type { ChatContextMeterProps } from './chat-context-meter'\n\ndefineOptions({ name: 'DouChatContextMeter' })\n\nconst props = withDefaults(defineProps<ChatContextMeterProps>(), {\n used: 0,\n total: 0,\n warnAt: 0.8,\n dangerAt: 0.95,\n showLabel: false,\n})\n\nconst ns = useNamespace('chat-context-meter')\nconst { t } = useLocale()\n\nconst usage = computed(() => contextUsage(props.used, props.total))\nconst share = computed(() => usage.value.share)\nconst percent = computed(() => usage.value.percent)\nconst tone = computed(() =>\n share.value >= props.dangerAt ? 'danger' : share.value >= props.warnAt ? 'warning' : 'neutral',\n)\n// what a screen reader hears for the value; the ring shows no numbers\nconst valueText = computed(() =>\n t('chat.context', {\n used: compactNumber(usage.value.used),\n total: compactNumber(usage.value.total),\n percent: percent.value,\n }),\n)\n\n// an icon-only button sizes the ring as its icon: the label would spill out of it\nconst root = useTemplateRef<HTMLElement>('root')\nonMounted(() => {\n if (process.env.NODE_ENV === 'production' || !props.showLabel) return\n if (root.value?.parentElement?.closest('.dou-button.is-icon-only'))\n devWarn(\n '[dou-ui] DouChatContextMeter: `showLabel` inside an icon-only button spills out of it, as the button sizes the ring as its icon. Put the ring in the button’s `leading` slot and the percentage as its text.',\n )\n})\n\n// r = 6 on a 16 box; the circumference drives the dash\nconst CIRCUMFERENCE = 2 * Math.PI * 6\n</script>\n\n<template>\n <!-- only the ring: a tooltip or popover goes around it, so it takes no focus of its own; an `aria-label` passed in replaces the default name -->\n <span\n ref=\"root\"\n :class=\"[ns.b(), ns.m(tone)]\"\n role=\"meter\"\n :aria-label=\"t('chat.contextLabel')\"\n :aria-valuenow=\"percent\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n :aria-valuetext=\"valueText\"\n >\n <svg :class=\"ns.e('ring')\" viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <circle :class=\"ns.e('track')\" cx=\"8\" cy=\"8\" r=\"6\" />\n <circle\n :class=\"ns.e('bar')\"\n cx=\"8\"\n cy=\"8\"\n r=\"6\"\n :stroke-dasharray=\"`${CIRCUMFERENCE * share} ${CIRCUMFERENCE}`\"\n />\n </svg>\n <span v-if=\"showLabel\" :class=\"ns.e('label')\">{{ percent }}%</span>\n </span>\n</template>\n"],"mappings":""}
@@ -1,7 +1,8 @@
1
1
  import { withInstall } from "../../utils/install.js";
2
+ import { compactNumber, contextUsage } from "./chat-context-meter.js";
2
3
  import chat_context_meter_default from "./chat-context-meter2.js";
3
4
  // src/components/chat-context-meter/index.ts
4
5
  var DouChatContextMeter = withInstall(chat_context_meter_default);
5
- export { DouChatContextMeter, DouChatContextMeter as default };
6
+ export { DouChatContextMeter, DouChatContextMeter as default, compactNumber, contextUsage };
6
7
 
7
8
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["ChatContextMeter"],"sources":["../../../src/components/chat-context-meter/index.ts"],"sourcesContent":["import { withInstall } from '../../utils/install'\nimport ChatContextMeter from './chat-context-meter.vue'\n\nexport const DouChatContextMeter = withInstall(ChatContextMeter)\nexport default DouChatContextMeter\n\nexport type * from './chat-context-meter'\nexport type ChatContextMeterInstance = InstanceType<typeof ChatContextMeter>\n\ndeclare module 'vue' {\n export interface GlobalComponents {\n DouChatContextMeter: typeof DouChatContextMeter\n }\n}\n"],"mappings":";;;AAGA,IAAa,sBAAsB,YAAYA,0BAAgB"}
1
+ {"version":3,"file":"index.js","names":["ChatContextMeter"],"sources":["../../../src/components/chat-context-meter/index.ts"],"sourcesContent":["import { withInstall } from '../../utils/install'\nimport ChatContextMeter from './chat-context-meter.vue'\n\nexport const DouChatContextMeter = withInstall(ChatContextMeter)\nexport default DouChatContextMeter\n\nexport type * from './chat-context-meter'\nexport { compactNumber, contextUsage } from './chat-context-meter'\nexport type ChatContextMeterInstance = InstanceType<typeof ChatContextMeter>\n\ndeclare module 'vue' {\n export interface GlobalComponents {\n DouChatContextMeter: typeof DouChatContextMeter\n }\n}\n"],"mappings":";;;;AAGA,IAAa,sBAAsB,YAAYA,0BAAgB"}
@@ -1,5 +1,3 @@
1
1
  import '@dou-ui/theme/core.css'
2
- import '@dou-ui/theme/components/overlay.css'
3
- import '@dou-ui/theme/components/kbd.css'
4
- import '@dou-ui/theme/components/tooltip.css'
2
+ import '@dou-ui/theme/components/button.css'
5
3
  import '@dou-ui/theme/components/chat-context-meter.css'
@@ -1 +1 @@
1
- {"version":3,"file":"chat-input.js","names":[],"sources":["../../../src/components/chat-input/chat-input.ts"],"sourcesContent":["import type { Component } from 'vue'\nimport type { Size } from '../../utils/types'\n\n/** An entry of the `/` command or `@` mention menu. */\nexport interface ChatInputOption {\n /** What is matched and handed back. For a mention it is also what gets inserted after `@`. */\n value: string\n /** Shown in the menu. Defaults to `value`. */\n label?: string\n /** A quieter line after the label. */\n description?: string\n /** An icon component before the label. */\n icon?: Component\n disabled?: boolean\n}\n\n/** `enter` sends on Enter (Shift+Enter breaks the line); `mod-enter` sends on Ctrl / ⌘ + Enter. */\nexport type ChatInputSubmitOn = 'enter' | 'mod-enter'\n\nexport interface ChatInputProps {\n /** The text, bound with `v-model`. */\n modelValue?: string\n /** Defaults to the locale's prompt. */\n placeholder?: string\n /** Which key sends. Keys pressed while an input method is composing never send. */\n submitOn?: ChatInputSubmitOn\n /**\n * A reply is being generated: the send button turns into a stop button.\n * Typing goes on meanwhile; once there is text, the button sends again\n * so the app can queue the message.\n */\n loading?: boolean\n /** Text size and padding; the corners and buttons follow. */\n size?: Size\n disabled?: boolean\n /** Rows shown when empty. */\n minRows?: number\n /** Rows to grow to before the text scrolls. */\n maxRows?: number\n /**\n * Whether sending is allowed. By default only when the text is not\n * blank; set it when, say, attachments alone may be sent.\n */\n canSubmit?: boolean\n /**\n * Commands offered when the text starts with `/`. Picking one removes\n * the typed `/…` and emits `command`.\n */\n commands?: ChatInputOption[]\n /**\n * Things to reference offered after `@`, e.g. files or people. Picking\n * one replaces the typed `@…` with `@value` and emits `mention`.\n */\n mentions?: ChatInputOption[]\n /** Where to render the `/` and `@` menu; `false` keeps it in place. */\n teleport?: string | HTMLElement | false\n}\n\nexport interface ChatInputEmits {\n 'update:modelValue': [value: string]\n /** The send key or button was pressed, with the text. Clearing it is up to you. */\n submit: [value: string]\n /** The stop button was pressed while `loading`. */\n stop: []\n /** A command was picked from the `/` menu. */\n command: [option: ChatInputOption]\n /** Something was picked from the `@` menu. */\n mention: [option: ChatInputOption]\n /** Files were pasted or dropped onto the input. */\n attach: [files: File[]]\n}\n\nexport interface ChatInputSlots {\n /** Above the text, e.g. `DouChatAttachments` or a quoted message. */\n header?: () => unknown\n /** The left of the bottom bar: buttons to attach files, pick a model and the like. */\n actions?: () => unknown\n /** Replaces the inside of each menu entry. */\n option?: (props: { option: ChatInputOption; trigger: '/' | '@' }) => unknown\n /** Replaces the send / stop button. */\n submit?: (props: {\n submit: () => void\n stop: () => void\n loading: boolean\n disabled: boolean\n }) => unknown\n}\n\nexport interface ChatInputExpose {\n /** The native `<textarea>`. */\n textarea: HTMLTextAreaElement | null\n focus: () => void\n blur: () => void\n /** Send as if the send key were pressed. */\n submit: () => void\n}\n\n/** The `/` or `@` token the caret is in, if any. */\nexport interface ChatInputToken {\n trigger: '/' | '@'\n /** Typed after the trigger. */\n query: string\n /** Where the trigger character is. */\n start: number\n /** Where the token ends (the caret). */\n end: number\n}\n\n/**\n * Find the token being typed at `caret`. A `/` counts only at the very\n * start of the text; an `@` at the start or after white space. The query\n * holds no white space.\n */\nexport function findToken(text: string, caret: number): ChatInputToken | null {\n let start = caret\n while (start > 0 && !/\\s/.test(text[start - 1]!)) start--\n const word = text.slice(start, caret)\n const trigger = word[0]\n if (trigger === '/' && text.slice(0, start).trim() === '')\n return { trigger, query: word.slice(1), start, end: caret }\n if (trigger === '@') return { trigger, query: word.slice(1), start, end: caret }\n return null\n}\n"],"mappings":";;;;;;AAiHA,SAAgB,UAAU,MAAc,OAAsC;CAC5E,IAAI,QAAQ;CACZ,OAAO,QAAQ,KAAK,CAAC,KAAK,KAAK,KAAK,QAAQ,EAAG,GAAG;CAClD,MAAM,OAAO,KAAK,MAAM,OAAO,KAAK;CACpC,MAAM,UAAU,KAAK;CACrB,IAAI,YAAY,OAAO,KAAK,MAAM,GAAG,KAAK,CAAC,CAAC,KAAK,MAAM,IACrD,OAAO;EAAE;EAAS,OAAO,KAAK,MAAM,CAAC;EAAG;EAAO,KAAK;CAAM;CAC5D,IAAI,YAAY,KAAK,OAAO;EAAE;EAAS,OAAO,KAAK,MAAM,CAAC;EAAG;EAAO,KAAK;CAAM;CAC/E,OAAO;AACT"}
1
+ {"version":3,"file":"chat-input.js","names":[],"sources":["../../../src/components/chat-input/chat-input.ts"],"sourcesContent":["import type { Component } from 'vue'\nimport type { Size } from '../../utils/types'\n\n/** An entry of the `/` command or `@` mention menu. */\nexport interface ChatInputOption {\n /**\n * Handed back when picked; for a mention it is also what gets inserted\n * after `@`, and so matched too. A command's value is never shown and\n * is matched only when there is no `label`: it may be an id.\n */\n value: string\n /** Shown in the menu and matched against what is typed. Defaults to `value`. */\n label?: string\n /** More words that find it, e.g. other names or pinyin. */\n keywords?: string[]\n /** A quieter line after the label; matched too. */\n description?: string\n /** An icon component before the label. */\n icon?: Component\n disabled?: boolean\n}\n\n/** Whether an option matches what is typed after the `/` or `@`. */\nexport type ChatInputFilter = (\n option: ChatInputOption,\n query: string,\n trigger: '/' | '@',\n) => boolean\n/** `true` matches as described under `filter`, `false` lists every option as given. */\nexport type ChatInputFilterMode = boolean | ChatInputFilter\n\n/** `enter` sends on Enter (Shift+Enter breaks the line); `mod-enter` sends on Ctrl / ⌘ + Enter. */\nexport type ChatInputSubmitOn = 'enter' | 'mod-enter'\n\nexport interface ChatInputProps {\n /** The text, bound with `v-model`. */\n modelValue?: string\n /** Defaults to the locale's prompt. */\n placeholder?: string\n /** Which key sends. Keys pressed while an input method is composing never send. */\n submitOn?: ChatInputSubmitOn\n /**\n * A reply is being generated: the send button turns into a stop button.\n * Typing goes on meanwhile; once there is text, the button sends again\n * so the app can queue the message.\n */\n loading?: boolean\n /** Text size and padding; the corners and buttons follow. */\n size?: Size\n disabled?: boolean\n /** Rows shown when empty. */\n minRows?: number\n /** Rows to grow to before the text scrolls. */\n maxRows?: number\n /**\n * Whether sending is allowed. By default only when the text is not\n * blank; set it when, say, attachments alone may be sent.\n */\n canSubmit?: boolean\n /**\n * Commands offered when the text starts with `/`. Picking one removes\n * the typed `/…` and emits `command`.\n */\n commands?: ChatInputOption[]\n /**\n * Things to reference offered after `@`, e.g. files or people. Picking\n * one replaces the typed `@…` with `@value` and emits `mention`.\n */\n mentions?: ChatInputOption[]\n /**\n * How options match what is typed after the trigger. By default what\n * the person sees holds it, ignoring case: the label (or the value, when\n * there is no label), a mention's value, the description and `keywords`.\n * `false` lists them all as given, e.g. results already looked up with\n * `search`. Give `{ '@': false }` to set the `/` and `@` menus apart;\n * a trigger left out matches by default.\n */\n filter?: ChatInputFilterMode | { '/'?: ChatInputFilterMode; '@'?: ChatInputFilterMode }\n /** Wait this many ms after the last keystroke before emitting `search`. */\n searchDelay?: number\n /** Where to render the `/` and `@` menu; `false` keeps it in place. */\n teleport?: string | HTMLElement | false\n}\n\nexport interface ChatInputEmits {\n 'update:modelValue': [value: string]\n /** The send key or button was pressed, with the text. Clearing it is up to you. */\n submit: [value: string]\n /** The stop button was pressed while `loading`. */\n stop: []\n /** A command was picked from the `/` menu. */\n command: [option: ChatInputOption]\n /** Something was picked from the `@` menu. */\n mention: [option: ChatInputOption]\n /**\n * The text after a `/` or `@` changed (after `searchDelay`), and when one\n * is typed: look options up somewhere else and replace `commands` or\n * `mentions` with them, usually with `filter` set to `false`.\n */\n search: [query: string, trigger: '/' | '@']\n /** Files were pasted or dropped onto the input. */\n attach: [files: File[]]\n}\n\nexport interface ChatInputSlots {\n /** Above the text, e.g. `DouChatAttachments` or a quoted message. */\n header?: () => unknown\n /** The left of the bottom bar: buttons to attach files, pick a model and the like. */\n actions?: () => unknown\n /** Replaces the inside of each menu entry. */\n option?: (props: { option: ChatInputOption; trigger: '/' | '@' }) => unknown\n /** Replaces the send / stop button. */\n submit?: (props: {\n submit: () => void\n stop: () => void\n loading: boolean\n disabled: boolean\n }) => unknown\n}\n\nexport interface ChatInputExpose {\n /** The native `<textarea>`. */\n textarea: HTMLTextAreaElement | null\n focus: () => void\n blur: () => void\n /** Send as if the send key were pressed. */\n submit: () => void\n}\n\n/** The `/` or `@` token the caret is in, if any. */\nexport interface ChatInputToken {\n trigger: '/' | '@'\n /** Typed after the trigger. */\n query: string\n /** Where the trigger character is. */\n start: number\n /** Where the token ends (the caret). */\n end: number\n}\n\n/**\n * Find the token being typed at `caret`. A `/` counts only at the very\n * start of the text; an `@` at the start or after white space. The query\n * holds no white space.\n */\nexport function findToken(text: string, caret: number): ChatInputToken | null {\n let start = caret\n while (start > 0 && !/\\s/.test(text[start - 1]!)) start--\n const word = text.slice(start, caret)\n const trigger = word[0]\n if (trigger === '/' && text.slice(0, start).trim() === '')\n return { trigger, query: word.slice(1), start, end: caret }\n if (trigger === '@') return { trigger, query: word.slice(1), start, end: caret }\n return null\n}\n"],"mappings":";;;;;;AAiJA,SAAgB,UAAU,MAAc,OAAsC;CAC5E,IAAI,QAAQ;CACZ,OAAO,QAAQ,KAAK,CAAC,KAAK,KAAK,KAAK,QAAQ,EAAG,GAAG;CAClD,MAAM,OAAO,KAAK,MAAM,OAAO,KAAK;CACpC,MAAM,UAAU,KAAK;CACrB,IAAI,YAAY,OAAO,KAAK,MAAM,GAAG,KAAK,CAAC,CAAC,KAAK,MAAM,IACrD,OAAO;EAAE;EAAS,OAAO,KAAK,MAAM,CAAC;EAAG;EAAO,KAAK;CAAM;CAC5D,IAAI,YAAY,KAAK,OAAO;EAAE;EAAS,OAAO,KAAK,MAAM,CAAC;EAAG;EAAO,KAAK;CAAM;CAC/E,OAAO;AACT"}