@bagelink/vue 1.16.0 → 1.17.6

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 (128) hide show
  1. package/dist/assetTransport.d.ts +28 -0
  2. package/dist/assetTransport.d.ts.map +1 -0
  3. package/dist/assetTransport.test.d.ts +2 -0
  4. package/dist/assetTransport.test.d.ts.map +1 -0
  5. package/dist/assets.d.ts +65 -0
  6. package/dist/assets.d.ts.map +1 -0
  7. package/dist/assets.test.d.ts +2 -0
  8. package/dist/assets.test.d.ts.map +1 -0
  9. package/dist/components/AddressSearch.vue.d.ts +40 -36
  10. package/dist/components/AddressSearch.vue.d.ts.map +1 -1
  11. package/dist/components/ContextMenu.vue.d.ts +518 -0
  12. package/dist/components/ContextMenu.vue.d.ts.map +1 -0
  13. package/dist/components/Dropdown.types.d.ts +25 -0
  14. package/dist/components/Dropdown.types.d.ts.map +1 -0
  15. package/dist/components/Dropdown.vue.d.ts +20 -15
  16. package/dist/components/Dropdown.vue.d.ts.map +1 -1
  17. package/dist/components/FilterQuery.vue.d.ts +1 -1
  18. package/dist/components/FilterQuery.vue.d.ts.map +1 -1
  19. package/dist/components/Icon/Icon.vue.d.ts +0 -1
  20. package/dist/components/Icon/Icon.vue.d.ts.map +1 -1
  21. package/dist/components/Icon/constants.d.ts +0 -1
  22. package/dist/components/Icon/constants.d.ts.map +1 -1
  23. package/dist/components/Icon/types.d.ts +2 -3
  24. package/dist/components/Icon/types.d.ts.map +1 -1
  25. package/dist/components/Image.vue.d.ts +7 -1
  26. package/dist/components/Image.vue.d.ts.map +1 -1
  27. package/dist/components/Swiper.vue.d.ts +1 -1
  28. package/dist/components/draggable/useDraggable.d.ts.map +1 -1
  29. package/dist/components/form/inputs/IconPickerInput.vue.d.ts +48 -37
  30. package/dist/components/form/inputs/IconPickerInput.vue.d.ts.map +1 -1
  31. package/dist/components/form/inputs/RichText/components/EditorToolbar.vue.d.ts.map +1 -1
  32. package/dist/components/form/inputs/RichText/composables/useCommands.d.ts.map +1 -1
  33. package/dist/components/form/inputs/RichText/composables/useEditor.d.ts +3 -0
  34. package/dist/components/form/inputs/RichText/composables/useEditor.d.ts.map +1 -1
  35. package/dist/components/form/inputs/RichText/composables/useEditorKeyboard.d.ts +1 -1
  36. package/dist/components/form/inputs/RichText/composables/useEditorKeyboard.d.ts.map +1 -1
  37. package/dist/components/form/inputs/RichText/index.vue.d.ts.map +1 -1
  38. package/dist/components/form/inputs/RichText/utils/commands.d.ts.map +1 -1
  39. package/dist/components/form/inputs/RichText/utils/selection.d.ts +2 -0
  40. package/dist/components/form/inputs/RichText/utils/selection.d.ts.map +1 -1
  41. package/dist/components/form/inputs/RichText/utils/table.d.ts +34 -8
  42. package/dist/components/form/inputs/RichText/utils/table.d.ts.map +1 -1
  43. package/dist/components/form/inputs/SelectInput.vue.d.ts +71 -63
  44. package/dist/components/form/inputs/SelectInput.vue.d.ts.map +1 -1
  45. package/dist/components/form/inputs/TelInput.vue.d.ts +2 -2
  46. package/dist/components/form/inputs/Upload/AssetUploadInput.vue.d.ts +11 -0
  47. package/dist/components/form/inputs/Upload/AssetUploadInput.vue.d.ts.map +1 -0
  48. package/dist/components/form/inputs/Upload/UploadInput.vue.d.ts +2 -2
  49. package/dist/components/form/inputs/Upload/UploadInput.vue.d.ts.map +1 -1
  50. package/dist/components/index.d.ts +3 -1
  51. package/dist/components/index.d.ts.map +1 -1
  52. package/dist/components/lightbox/AssetPreview.vue.d.ts +9 -0
  53. package/dist/components/lightbox/AssetPreview.vue.d.ts.map +1 -0
  54. package/dist/components/lightbox/Lightbox.vue.d.ts.map +1 -1
  55. package/dist/components/lightbox/LightboxImage.vue.d.ts +2 -1
  56. package/dist/components/lightbox/LightboxImage.vue.d.ts.map +1 -1
  57. package/dist/components/lightbox/index.d.ts.map +1 -1
  58. package/dist/components/lightbox/lightbox.types.d.ts +7 -0
  59. package/dist/components/lightbox/lightbox.types.d.ts.map +1 -1
  60. package/dist/composables/index.d.ts +1 -1
  61. package/dist/composables/index.d.ts.map +1 -1
  62. package/dist/composables/useBoundedRectDrag.d.ts.map +1 -1
  63. package/dist/composables/useImageSrc.d.ts +8 -4
  64. package/dist/composables/useImageSrc.d.ts.map +1 -1
  65. package/dist/composables/usePointerSession.d.ts +14 -3
  66. package/dist/composables/usePointerSession.d.ts.map +1 -1
  67. package/dist/core.css +3 -3
  68. package/dist/directives/vResize.d.ts.map +1 -1
  69. package/dist/form-flow/FormFlowPlayer.vue.d.ts +3 -3
  70. package/dist/form-flow/FormFlowPlayer.vue.d.ts.map +1 -1
  71. package/dist/form-flow/form-flow.d.ts +13 -6
  72. package/dist/form-flow/form-flow.d.ts.map +1 -1
  73. package/dist/form-flow/schema-fields.d.ts +6 -0
  74. package/dist/form-flow/schema-fields.d.ts.map +1 -1
  75. package/dist/index.cjs +240 -153
  76. package/dist/index.css +1 -1
  77. package/dist/index.d.ts +3 -0
  78. package/dist/index.d.ts.map +1 -1
  79. package/dist/index.mjs +24167 -23417
  80. package/dist/style.css +3 -3
  81. package/dist/types/BagelForm.d.ts +5 -1
  82. package/dist/types/BagelForm.d.ts.map +1 -1
  83. package/package.json +1 -1
  84. package/src/assetTransport.test.ts +75 -0
  85. package/src/assetTransport.ts +98 -0
  86. package/src/assets.test.ts +82 -0
  87. package/src/assets.ts +162 -0
  88. package/src/components/ContextMenu.vue +113 -0
  89. package/src/components/Dropdown.types.ts +27 -0
  90. package/src/components/Dropdown.vue +129 -64
  91. package/src/components/FilterQuery.vue +1 -1
  92. package/src/components/Icon/Icon.vue +8 -30
  93. package/src/components/Icon/constants.ts +0 -166
  94. package/src/components/Icon/types.ts +2 -3
  95. package/src/components/Image.vue +19 -3
  96. package/src/components/draggable/useDraggable.ts +67 -100
  97. package/src/components/form/inputs/IconPickerInput.vue +14 -9
  98. package/src/components/form/inputs/RichText/components/EditorToolbar.vue +43 -111
  99. package/src/components/form/inputs/RichText/composables/useCommands.ts +32 -54
  100. package/src/components/form/inputs/RichText/composables/useEditor.ts +45 -171
  101. package/src/components/form/inputs/RichText/composables/useEditorKeyboard.ts +90 -14
  102. package/src/components/form/inputs/RichText/index.vue +1195 -1210
  103. package/src/components/form/inputs/RichText/utils/commands.ts +689 -1028
  104. package/src/components/form/inputs/RichText/utils/selection.ts +66 -41
  105. package/src/components/form/inputs/RichText/utils/table.ts +798 -136
  106. package/src/components/form/inputs/SelectInput.vue +1 -1
  107. package/src/components/form/inputs/Upload/AssetUploadInput.vue +67 -0
  108. package/src/components/form/inputs/Upload/UploadInput.vue +5 -1
  109. package/src/components/index.ts +3 -1
  110. package/src/components/lightbox/AssetPreview.vue +16 -0
  111. package/src/components/lightbox/Lightbox.vue +8 -3
  112. package/src/components/lightbox/LightboxImage.vue +4 -3
  113. package/src/components/lightbox/index.ts +29 -4
  114. package/src/components/lightbox/lightbox.types.ts +5 -1
  115. package/src/composables/index.ts +1 -1
  116. package/src/composables/useBoundedRectDrag.ts +9 -12
  117. package/src/composables/useImageSrc.ts +47 -37
  118. package/src/composables/usePointerSession.ts +57 -12
  119. package/src/directives/vResize.ts +6 -7
  120. package/src/form-flow/form-flow.ts +31 -7
  121. package/src/form-flow/schema-fields.ts +28 -1
  122. package/src/index.ts +3 -0
  123. package/src/styles/core.css +1 -18
  124. package/src/types/BagelForm.ts +5 -1
  125. package/dist/components/form/inputs/RichText/utils/formatting.d.ts +0 -10
  126. package/dist/components/form/inputs/RichText/utils/formatting.d.ts.map +0 -1
  127. package/src/components/form/inputs/RichText/components/gridBox.vue +0 -58
  128. package/src/components/form/inputs/RichText/utils/formatting.ts +0 -331
@@ -98,6 +98,10 @@ export interface UploadInputValueObject {
98
98
  src?: string;
99
99
  }
100
100
  export interface UploadInputProps extends BagelInputShellProps {
101
+ /** Opt-in stable reference output; defaults to legacy path-key behavior. */
102
+ assetMode?: boolean;
103
+ /** Asset delivery policy. Defaults to protected; website/media fields use public. */
104
+ assetVisibility?: import('../assets').AssetVisibility;
101
105
  id?: string;
102
106
  name?: string;
103
107
  label?: string;
@@ -106,7 +110,7 @@ export interface UploadInputProps extends BagelInputShellProps {
106
110
  * Path-key string(s). Legacy/migrated records may also provide an image object
107
111
  * (e.g. `{ imageURL, imageName, extension, altText }`); it is normalized internally.
108
112
  */
109
- modelValue?: string | string[] | UploadInputValueObject | (string | UploadInputValueObject)[];
113
+ modelValue?: string | string[] | UploadInputValueObject | import('../assets').AssetReference | (string | UploadInputValueObject | import('../assets').AssetReference)[];
110
114
  /** Optional upload handler. When omitted, the shared file-storage uploader is used. */
111
115
  upload?: (file: File) => Promise<string>;
112
116
  width?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"BagelForm.d.ts","sourceRoot":"","sources":["../../src/types/BagelForm.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAA;AAC/D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAA;AACzD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAA;AACxE,OAAO,KAAK,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAA;AAC/E,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,KAAK,CAAA;AAIhC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAA;AAErF,UAAU,MAAM;IAAG,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,GAAG,CAAA;CAAE;AAI9C,MAAM,MAAM,KAAK,CAChB,CAAC,EACD,EAAE,SAAS,YAAY,GAAG,mBAAmB,IAC1C,QAAQ,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAA;AAG9C,KAAK,mBAAmB,CAAC,CAAC,IAAI;KAC5B,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KAAE,GAChD,GAAG,CAAC,GAAG,MAAM,IAAI,MAAM,EAAE,GACzB,KAAK;CACR,CAAC,MAAM,CAAC,CAAC,CAAA;AAGV,MAAM,MAAM,IAAI,CAAC,CAAC,EAAE,EAAE,SAAS,YAAY,GAAG,mBAAmB,IAC9D,QAAQ,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,SAAS,KAAK,CAAC,GAAG,CAAC,GAC3C,kBAAkB,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAChC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,mBAAmB,CAAC,CAAC,CAAC,GAAG,GAAG,MAAM,CAAC,GAAG,MAAM,cAAc,MAAM,EAAE,CAAA;AAErF,uFAAuF;AACvF,MAAM,MAAM,QAAQ,CAAC,CAAC,EAAE,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC,IACtC,OAAO,SAAS,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,OAAO,GAAG,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;AAElD,sEAAsE;AACtE,MAAM,MAAM,aAAa,CAAC,CAAC,EAAE,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC,IAC3C,CAAC,SAAS,MAAM,GACf,CAAC,SAAS,MAAM,CAAC,GAChB,CAAC,CAAC,CAAC,CAAC,GACJ,GAAG,GACJ,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;AAIlB,MAAM,MAAM,cAAc,GACrB,MAAM,GACP,MAAM,GACN,OAAO,GACP,SAAS,GACT;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CAAE,CAAA;AAE1B,MAAM,MAAM,WAAW,CAAC,CAAC,EAAE,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC,IAAI,CAC/C,KAAK,EAAE,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,EAC1B,GAAG,CAAC,EAAE,CAAC,KACH,cAAc,CAAA;AAEnB,MAAM,WAAW,UAAU,CAAC,CAAC,EAAE,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC;IAC/C,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,GAAG,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;CACjD;AAED,MAAM,MAAM,YAAY,CAAC,CAAC,EAAE,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC,IACxC,MAAM,GACP,CACC;IACD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,GAAG,MAAM,CAAA;CACtB,GACC,MAAM,GACN,MAAM,GACN,OAAO,GACP;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CAAE,CACxB,EAAE,GACD,CAAC,CAAC,GAAG,CAAC,EAAE,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,CAAC,KAAK,MAAM,EAAE,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,GAC/F,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,CAAC,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;AAElF,MAAM,MAAM,OAAO,CAAC,CAAC,EAAE,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC,IACnC,MAAM,GACP,OAAO,GACP,CAAC,CAAC,GAAG,CAAC,EAAE,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,CAAC,KAAK,OAAO,CAAC,CAAA;AAEzD,MAAM,MAAM,YAAY,CAAC,CAAC,EAAE,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC,IAAI,CAChD,GAAG,CAAC,EAAE,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,EACzB,OAAO,CAAC,EAAE,CAAC,KACP,MAAM,GAAG,SAAS,CAAA;AAEvB,MAAM,MAAM,WAAW,CAAC,CAAC,EAAE,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC,IAAI,CAC/C,GAAG,CAAC,EAAE,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,EACzB,OAAO,CAAC,EAAE,CAAC,KACP,GAAG,CAAA;AAER,MAAM,MAAM,QAAQ,CAAC,CAAC,EAAE,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC,IAAI,CAC5C,GAAG,CAAC,EAAE,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,EACzB,OAAO,CAAC,EAAE,CAAC,KACP,OAAO,CAAA;AAIZ,MAAM,MAAM,OAAO,CAAC,CAAC,EAAE,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE;IACnD,GAAG,CAAC,EAAE,CAAC,CAAA;IACP,KAAK,EAAE,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;CAC3B,KAAK,KAAK,CAAA;AAEX,MAAM,WAAW,YAAY,CAC5B,CAAC,EACD,EAAE,SAAS,YAAY,GAAG,mBAAmB;IAE7C,GAAG,EAAE,GAAG,CAAA;IACR,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,MAAM,CAAA;IACzB,KAAK,CAAC,EAAE,GAAG,CAAA;IACX,GAAG,CAAC,EAAE,GAAG,CAAA;IACT,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAC3B,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,CAAC,KAAK,IAAI,CAAA;IAC1C,SAAS,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,CAAC,KAAK,GAAG,CAAA;IAC3C,QAAQ,CAAC,EAAE,YAAY,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAA;CAChC;AAGD,KAAK,mBAAmB,CAAC,CAAC,EAAE,EAAE,SAAS,YAAY,GAAG,mBAAmB,IAAI;KAC3E,CAAC,IAAI,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,cAAc,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;CAC5C,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAA;AAEd,MAAM,MAAM,WAAW,CACtB,CAAC,EACD,CAAC,SAAS,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC,EACrB,EAAE,SAAS,YAAY,GAAG,mBAAmB,IAC1C,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,YAAY,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,KAAK,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,MAAM,GAAG,mBAAmB,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;AAEpG,MAAM,WAAW,cAAc,CAC9B,CAAC,EACD,CAAC,SAAS,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC,EACrB,EAAE,SAAS,YAAY,GAAG,mBAAmB;IAE7C,KAAK,CAAC,EAAE,MAAM,GAAG,GAAG,CAAA;IACpB,IAAI,CAAC,EAAE,CAAC,CAAA;IACR,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,OAAO,CAAC,EAAE,cAAc,GAAG,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IAC5C,OAAO,CAAC,EAAE,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IAC1B,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,SAAS,CAAC,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IAC9B,UAAU,CAAC,EAAE,WAAW,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAA;IAC9C,OAAO,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAA;KAAE,CAAA;IAC9D,cAAc,CAAC,EAAE,GAAG,CAAA;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IACtB,WAAW,CAAC,EAAE,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IAC/B,UAAU,CAAC,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IAC3B,UAAU,CAAC,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;CAC/B;AAED,MAAM,MAAM,KAAK,CAChB,CAAC,EACD,EAAE,SAAS,YAAY,GAAG,mBAAmB,IAC1C,mBAAmB,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;AAE9B,MAAM,MAAM,WAAW,CACtB,CAAC,EACD,EAAE,SAAS,YAAY,GAAG,mBAAmB,IAC1C,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,YAAY,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;AAEtC,MAAM,MAAM,cAAc,CACzB,CAAC,EACD,EAAE,SAAS,YAAY,GAAG,mBAAmB,IAC1C,CAAC,WAAW,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,cAAc,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAA;AAI/D,MAAM,WAAW,kBAAkB;IAClC,QAAQ,CAAC,EAAE,YAAY,CAAC;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,EAAE,MAAM,CAAC,CAAA;IAC3D,WAAW,CAAC,EAAE,MAAM,GAAG,CAAA;CACvB;AAED,qFAAqF;AACrF,MAAM,WAAW,sBAAsB;IACtC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;CACZ;AAED,MAAM,WAAW,gBAAiB,SAAQ,oBAAoB;IAC7D,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,sBAAsB,GAAG,CAAC,MAAM,GAAG,sBAAsB,CAAC,EAAE,CAAA;IAC7F,uFAAuF;IACvF,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;IACxC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IACxB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,+DAA+D;IAC/D,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,KAAK,CAAC,EAAE,UAAU,GAAG,OAAO,CAAA;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,aAAa,CAAA;IAC1C,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,0FAA0F;IAC1F,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IAC1B,cAAc,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;CAChC"}
1
+ {"version":3,"file":"BagelForm.d.ts","sourceRoot":"","sources":["../../src/types/BagelForm.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@bagelink/vue",
3
3
  "type": "module",
4
- "version": "1.16.0",
4
+ "version": "1.17.6",
5
5
  "description": "Bagel core sdk packages",
6
6
  "author": {
7
7
  "name": "Bagel Studio",
@@ -0,0 +1,75 @@
1
+ import { describe, expect, it, vi } from 'vitest'
2
+ import { configureAssetClient, createAssetHttpTransport, type AssetFetch } from './assetTransport'
3
+ import { createAssetClient } from './assets'
4
+ import type { ApiTransport } from '@bagelink/sdk'
5
+ import { createApp, ref } from 'vue'
6
+
7
+ const session = { asset_id: 'a', upload_id: 'u', status: 'ready' }
8
+ const json = (value: unknown, status = 200) => new Response(JSON.stringify(value), { status })
9
+ const signal = () => new AbortController().signal
10
+
11
+ describe('asset REST transport', () => {
12
+ it('starts a session and sends unchanged raw bytes, returning the public id', async () => {
13
+ const fetcher = vi.fn<AssetFetch>().mockResolvedValueOnce(json(session)).mockResolvedValueOnce(json(session))
14
+ const transport = createAssetHttpTransport({ baseURL: 'https://api.example/api', fetch: fetcher })
15
+ const file = new File(['original'], 'test.heic')
16
+ expect(await transport.upload(file, signal())).toEqual({ asset_id: 'a' })
17
+ expect(String(fetcher.mock.calls[0]![0])).toBe('https://api.example/api/assets/uploads')
18
+ expect(fetcher.mock.calls[0]![1]?.body).toBe('{"name":"test.heic"}')
19
+ expect(fetcher.mock.calls[1]![1]?.body).toBe(file)
20
+ expect(new Headers(fetcher.mock.calls[1]![1]?.headers).get('Content-Type')).toBe('application/octet-stream')
21
+ })
22
+
23
+ it('fails closed for rejected completion and HTTP errors', async () => {
24
+ const fetcher = vi.fn<AssetFetch>().mockResolvedValueOnce(json(session))
25
+ .mockResolvedValueOnce(json({ ...session, status: 'rejected' })).mockResolvedValueOnce(json({}, 403))
26
+ const transport = createAssetHttpTransport({ baseURL: 'https://api.example', fetch: fetcher })
27
+ await expect(transport.upload(new File(['x'], 'x'), signal())).rejects.toThrow('not ready')
28
+ await expect(transport.upload(new File(['x'], 'x'), signal())).rejects.toThrow('(403)')
29
+ })
30
+
31
+ it('does not PUT if session creation fails', async () => {
32
+ const fetcher = vi.fn<AssetFetch>().mockResolvedValueOnce(json({}, 503))
33
+ const transport = createAssetHttpTransport({ baseURL: 'https://api.example', fetch: fetcher })
34
+ await expect(transport.upload(new File(['x'], 'x'), signal())).rejects.toThrow('(503)')
35
+ expect(fetcher).toHaveBeenCalledTimes(1)
36
+ })
37
+
38
+ it('configureAssetClient provides a client that builds public URLs', () => {
39
+ const transport = { axios: { defaults: { baseURL: 'https://api.example/api' }, request: vi.fn() } } as unknown as ApiTransport
40
+ const assets = configureAssetClient({ transport, deliveryBaseUrl: 'https://cdn.bgl.dev/auctentic' })
41
+ expect(assets.client.assetUrl({ asset_id: 'a' })).toBe('https://cdn.bgl.dev/auctentic/a')
42
+ expect(assets.client.assetUrl({ asset_id: 'a' }, 'website')).toBe('https://cdn.bgl.dev/auctentic/a?fmt=webp')
43
+ expect(assets.client.assetUrl({ asset_id: 'a' }, 'social')).toBe('https://cdn.bgl.dev/auctentic/a?w=1200&h=630&fmt=jpeg&fit=cover')
44
+ })
45
+
46
+ it('clears in-flight uploads on session change', async () => {
47
+ let requestSignal: AbortSignal | null | undefined
48
+ const fetcher = vi.fn<AssetFetch>((config: any) => {
49
+ requestSignal = config?.signal
50
+ return new Promise((_resolve, reject) => requestSignal?.addEventListener('abort', () => reject(requestSignal?.reason))
51
+ )
52
+ })
53
+ const transport = { axios: { defaults: { baseURL: 'https://api.example' }, request: fetcher } } as unknown as ApiTransport
54
+ const sessionKey = ref('a')
55
+ const assets = configureAssetClient({ transport, deliveryBaseUrl: 'https://cdn.bgl.dev/auctentic', sessionKey })
56
+ createApp({}).use(assets)
57
+ const promise = assets.client.upload(new File(['x'], 'x'))
58
+ sessionKey.value = 'b'
59
+ await expect(promise).rejects.toMatchObject({ name: 'AbortError' })
60
+ expect(requestSignal?.aborted).toBe(true)
61
+ })
62
+ })
63
+
64
+ describe('asset client upload cancellation', () => {
65
+ it('does not complete after clearSession', async () => {
66
+ let finish!: (response: Response) => void
67
+ const fetcher = vi.fn<AssetFetch>().mockImplementationOnce(() => new Promise(resolve => { finish = resolve }))
68
+ const client = createAssetClient(createAssetHttpTransport({ baseURL: 'https://api.example', fetch: fetcher }), 'https://cdn.bgl.dev/auctentic')
69
+ const promise = client.upload(new File(['x'], 'x'))
70
+ client.clearSession()
71
+ finish(json(session))
72
+ await expect(promise).rejects.toMatchObject({ name: 'AbortError' })
73
+ expect(fetcher).toHaveBeenCalledTimes(1)
74
+ })
75
+ })
@@ -0,0 +1,98 @@
1
+ import { createAssetClient, ASSET_CLIENT_KEY, type AssetTransport } from './assets'
2
+ import type { ApiTransport } from '@bagelink/sdk'
3
+ import { watch, toValue, type App, type MaybeRefOrGetter } from 'vue'
4
+
5
+ export type AssetFetch = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>
6
+
7
+ export interface AssetHttpOptions {
8
+ /** Absolute API base, optionally with a path prefix. */
9
+ baseURL: string
10
+ headers?: () => HeadersInit
11
+ fetch?: AssetFetch
12
+ credentials?: RequestCredentials
13
+ /** Reuse the app's authenticated axios instance, including tenant interceptors. */
14
+ apiTransport?: ApiTransport
15
+ }
16
+
17
+ interface UploadResponse {
18
+ asset_id: string
19
+ upload_id: string
20
+ status: string
21
+ }
22
+
23
+ /** Concrete REST adapter. Public-by-default: upload only; display is a client-built URL. */
24
+ export function createAssetHttpTransport(options: AssetHttpOptions): AssetTransport {
25
+ const base = new URL(options.baseURL.endsWith('/') ? options.baseURL : `${options.baseURL}/`)
26
+ if (!['http:', 'https:'].includes(base.protocol) || base.username || base.password) throw new Error('Invalid API base')
27
+ const request = options.fetch ?? globalThis.fetch
28
+ async function send<T>(path: string, init: RequestInit, signal: AbortSignal): Promise<T> {
29
+ signal.throwIfAborted()
30
+ const headers = new Headers(options.headers?.())
31
+ new Headers(init.headers).forEach((value, key) => headers.set(key, value))
32
+ if (options.apiTransport) {
33
+ const requestHeaders: Record<string, string> = {}
34
+ headers.forEach((value, key) => { requestHeaders[key] = value })
35
+ const response = await options.apiTransport.axios.request<T>({
36
+ url: `assets/${path}`, method: init.method, data: init.body,
37
+ headers: requestHeaders, signal,
38
+ })
39
+ signal.throwIfAborted()
40
+ return response.data
41
+ }
42
+ const response = await request(new URL(`assets/${path}`, base), {
43
+ ...init, headers, signal, credentials: options.credentials ?? 'include', cache: 'no-store', redirect: 'error',
44
+ })
45
+ signal.throwIfAborted()
46
+ if (!response.ok) throw new Error(`Asset request failed (${response.status})`)
47
+ return await response.json() as T
48
+ }
49
+ return {
50
+ async upload(file, signal, uploadOptions) {
51
+ const started = await send<UploadResponse>('uploads', {
52
+ method: 'POST',
53
+ headers: { 'Content-Type': 'application/json' },
54
+ body: JSON.stringify({
55
+ name: file.name,
56
+ visibility: uploadOptions?.visibility ?? 'protected',
57
+ }),
58
+ }, signal)
59
+ if (!started.upload_id || !started.asset_id) throw new Error('Invalid upload session')
60
+ const completed = await send<UploadResponse>(`uploads/${encodeURIComponent(started.upload_id)}`, {
61
+ method: 'PUT', headers: { 'Content-Type': 'application/octet-stream' }, body: file,
62
+ }, signal)
63
+ if (completed.status !== 'ready' || completed.asset_id !== started.asset_id) {
64
+ throw new Error('Asset upload is not ready')
65
+ }
66
+ return { asset_id: completed.asset_id }
67
+ },
68
+ }
69
+ }
70
+
71
+ export interface ConfigureAssetClientOptions {
72
+ transport: ApiTransport
73
+ /** Public CDN base, e.g. `https://cdn.bgl.dev/auctentic`. Used to build asset URLs. */
74
+ deliveryBaseUrl: string
75
+ /** Identity + tenant key; must change on logout and account/tenant switch. */
76
+ sessionKey?: MaybeRefOrGetter<string | undefined>
77
+ }
78
+
79
+ /** Vue plugin; provides the asset client and clears uploads on session change. */
80
+ export function configureAssetClient(options: ConfigureAssetClientOptions) {
81
+ const baseURL = options.transport.axios.defaults.baseURL
82
+ if (!baseURL) throw new Error('Asset transport needs an API baseURL')
83
+ const transport = createAssetHttpTransport({
84
+ baseURL: new URL(baseURL, typeof location === 'undefined' ? undefined : location.origin).href,
85
+ apiTransport: options.transport,
86
+ })
87
+ const client = createAssetClient(transport, options.deliveryBaseUrl)
88
+ return {
89
+ client,
90
+ install(app: App) {
91
+ app.provide(ASSET_CLIENT_KEY, client)
92
+ const stop = options.sessionKey
93
+ ? watch(() => toValue(options.sessionKey), () => client.clearSession(), { flush: 'sync' })
94
+ : undefined
95
+ app.onUnmount(() => { stop?.(); client.clearSession() })
96
+ },
97
+ }
98
+ }
@@ -0,0 +1,82 @@
1
+ // @vitest-environment happy-dom
2
+ import { describe, expect, it, vi } from 'vitest'
3
+ import { createAssetClient, ASSET_CLIENT_KEY, useAssetDelivery, useAssetUpload, type AssetTransport } from './assets'
4
+ import { mount } from '@vue/test-utils'
5
+ import { defineComponent, nextTick } from 'vue'
6
+
7
+ const BASE = 'https://cdn.bgl.dev/auctentic'
8
+
9
+ function makeClient(upload?: AssetTransport['upload']) {
10
+ const transport = { upload: upload ?? (async () => ({ asset_id: 'a' })) }
11
+ return createAssetClient(transport, BASE)
12
+ }
13
+
14
+ describe('asset client', () => {
15
+ it('builds deterministic public URLs per purpose', () => {
16
+ const client = makeClient()
17
+ expect(client.assetUrl({ asset_id: 'a' })).toBe(`${BASE}/a`)
18
+ expect(client.assetUrl({ asset_id: 'a' }, 'original')).toBe(`${BASE}/a`)
19
+ expect(client.assetUrl({ asset_id: 'a' }, 'website')).toBe(`${BASE}/a?fmt=webp`)
20
+ expect(client.assetUrl({ asset_id: 'a' }, 'social')).toBe(`${BASE}/a?w=1200&h=630&fmt=jpeg&fit=cover`)
21
+ })
22
+
23
+ it('upload returns only the public id (version is ignored)', async () => {
24
+ const upload = vi.fn<AssetTransport['upload']>(async () => ({ asset_id: 'a', version_id: 'v1' }))
25
+ const client = makeClient(upload)
26
+ await expect(client.upload(new File(['x'], 'x'))).resolves.toEqual({ asset_id: 'a' })
27
+ })
28
+
29
+ it('clearSession aborts in-flight uploads and bumps revision', async () => {
30
+ const upload = vi.fn<AssetTransport['upload']>((_f, signal) => new Promise((_resolve, reject) => {
31
+ signal.addEventListener('abort', () => reject(new DOMException('x', 'AbortError')))
32
+ }))
33
+ const client = makeClient(upload)
34
+ const before = client.revision
35
+ const promise = client.upload(new File(['x'], 'x'))
36
+ client.clearSession()
37
+ await expect(promise).rejects.toMatchObject({ name: 'AbortError' })
38
+ expect(client.revision).toBe(before + 1)
39
+ })
40
+ })
41
+
42
+ describe('useAssetDelivery (public URL resolution)', () => {
43
+ it('resolves an asset reference to its public URL without a network call', async () => {
44
+ const client = makeClient()
45
+ let state!: ReturnType<typeof useAssetDelivery>
46
+ mount(defineComponent({
47
+ setup() { state = useAssetDelivery(() => ({ asset_id: 'a', representation: 'preview' })); return () => null },
48
+ }), { global: { provide: { [ASSET_CLIENT_KEY as symbol]: client } } })
49
+ await nextTick()
50
+ expect(state.url.value).toBe(`${BASE}/a?fmt=webp`)
51
+ expect(state.error.value).toBe(false)
52
+ })
53
+
54
+ it('sets error when no client is provided', async () => {
55
+ let state!: ReturnType<typeof useAssetDelivery>
56
+ mount(defineComponent({
57
+ setup() { state = useAssetDelivery(() => ({ asset_id: 'a' })); return () => null },
58
+ }))
59
+ await nextTick()
60
+ expect(state.url.value).toBeUndefined()
61
+ expect(state.error.value).toBe(true)
62
+ })
63
+ })
64
+
65
+ describe('useAssetUpload', () => {
66
+ it('rejects when no client is injected', async () => {
67
+ let upload!: ReturnType<typeof useAssetUpload>['upload']
68
+ mount(defineComponent({
69
+ setup() { upload = useAssetUpload().upload; return () => null },
70
+ }))
71
+ await expect(upload(new File(['x'], 'x'))).rejects.toThrow('Asset client is not configured')
72
+ })
73
+
74
+ it('uploads and returns the public reference', async () => {
75
+ const client = makeClient()
76
+ let upload!: ReturnType<typeof useAssetUpload>['upload']
77
+ mount(defineComponent({
78
+ setup() { upload = useAssetUpload().upload; return () => null },
79
+ }), { global: { provide: { [ASSET_CLIENT_KEY as symbol]: client } } })
80
+ await expect(upload(new File(['x'], 'x'))).resolves.toEqual({ asset_id: 'a' })
81
+ })
82
+ })
package/src/assets.ts ADDED
@@ -0,0 +1,162 @@
1
+ import { inject, onScopeDispose, ref, toValue, watch, type InjectionKey, type MaybeRefOrGetter } from 'vue'
2
+
3
+ /**
4
+ * Persist this reference, never a delivery URL. Assets are public-by-default;
5
+ * the id alone addresses the bytes. ``version_id`` is accepted for backward
6
+ * compatibility with callers that still emit it, but it is ignored: it no
7
+ * longer selects a version and never appears in a URL.
8
+ */
9
+ export interface AssetReference {
10
+ asset_id: string
11
+ version_id?: string
12
+ }
13
+
14
+ export type AssetVisibility = 'protected' | 'public'
15
+
16
+ export interface AssetUploadOptions {
17
+ /** Protected is the safe default. Website/media callers must opt into public. */
18
+ visibility?: AssetVisibility
19
+ }
20
+
21
+ /** Display purpose → on-demand transform query params (mirrors common/blox). */
22
+ export type AssetPurpose = 'original' | 'preview' | 'thumbnail' | 'website' | 'social'
23
+
24
+ const PURPOSE_PARAMS: Record<AssetPurpose, string> = {
25
+ original: '',
26
+ preview: 'fmt=webp',
27
+ thumbnail: 'fmt=webp&w=256',
28
+ website: 'fmt=webp',
29
+ social: 'w=1200&h=630&fmt=jpeg&fit=cover',
30
+ }
31
+
32
+ /** A display intent: a pinned asset plus an optional purpose/preset. */
33
+ export interface AssetDeliveryRequest extends AssetReference {
34
+ representation?: AssetPurpose
35
+ }
36
+
37
+ /** Separate facade: generated SDK namespaces remain unchanged. */
38
+ export interface AssetTransport {
39
+ upload(file: File, signal: AbortSignal, options?: AssetUploadOptions): Promise<AssetReference>
40
+ }
41
+
42
+ export interface AssetClient {
43
+ /** Upload original bytes; protected unless the caller explicitly opts into public. */
44
+ upload(file: File, signal?: AbortSignal, options?: AssetUploadOptions): Promise<AssetReference>
45
+ /** Build the public CDN URL for a reference + optional purpose. */
46
+ assetUrl(reference: AssetReference, purpose?: AssetPurpose): string
47
+ /** Abort in-flight uploads (logout / tenant / account switch). */
48
+ clearSession(): void
49
+ /** Monotonic counter bumped on clearSession; watchers can subscribe. */
50
+ revision: number
51
+ }
52
+
53
+ const abortError = () => new DOMException('Asset request cancelled', 'AbortError')
54
+
55
+ /** App/session scoped; no persistent storage or delivery cache (URLs are public). */
56
+ export function createAssetClient(
57
+ transport: AssetTransport,
58
+ deliveryBaseUrl: string,
59
+ ): AssetClient {
60
+ const controllers = new Set<AbortController>()
61
+ let revision = 0
62
+
63
+ function assetUrl(reference: AssetReference, purpose: AssetPurpose = 'original'): string {
64
+ const query = PURPOSE_PARAMS[purpose] ?? ''
65
+ const base = deliveryBaseUrl.replace(/\/+$/, '')
66
+ return query ? `${base}/${reference.asset_id}?${query}` : `${base}/${reference.asset_id}`
67
+ }
68
+
69
+ return {
70
+ get revision() { return revision },
71
+ assetUrl,
72
+ async upload(file: File, signal?: AbortSignal, options?: AssetUploadOptions): Promise<AssetReference> {
73
+ const controller = new AbortController()
74
+ const abort = () => controller.abort()
75
+ signal?.addEventListener('abort', abort, { once: true })
76
+ controllers.add(controller)
77
+ try {
78
+ if (signal?.aborted) controller.abort()
79
+ if (controller.signal.aborted) throw abortError()
80
+ const reference = await transport.upload(file, controller.signal, options)
81
+ if (controller.signal.aborted) throw abortError()
82
+ return { asset_id: reference.asset_id }
83
+ } finally {
84
+ controllers.delete(controller)
85
+ signal?.removeEventListener('abort', abort)
86
+ }
87
+ },
88
+ clearSession() {
89
+ for (const controller of controllers) controller.abort()
90
+ controllers.clear()
91
+ revision++
92
+ },
93
+ }
94
+ }
95
+
96
+ export const ASSET_CLIENT_KEY: InjectionKey<AssetClient> = Symbol('bagel:assets')
97
+
98
+ /** Opt-in upload state; original bytes are handed unchanged to the transport. */
99
+ export function useAssetUpload() {
100
+ const client = inject(ASSET_CLIENT_KEY, undefined)
101
+ const uploading = ref(false)
102
+ const reference = ref<AssetReference>()
103
+ let controller: AbortController | undefined
104
+ let generation = 0
105
+ function cancel() {
106
+ generation++
107
+ controller?.abort()
108
+ uploading.value = false
109
+ reference.value = undefined
110
+ }
111
+ async function upload(file: File, options?: AssetUploadOptions): Promise<AssetReference> {
112
+ cancel()
113
+ if (!client) throw new Error('Asset client is not configured')
114
+ const current = generation
115
+ controller = new AbortController()
116
+ uploading.value = true
117
+ try {
118
+ const result = await client.upload(file, controller.signal, options)
119
+ if (current !== generation) throw abortError()
120
+ reference.value = result
121
+ return result
122
+ } finally {
123
+ if (current === generation) uploading.value = false
124
+ }
125
+ }
126
+ const stop = client ? watch(() => client.revision, cancel, { flush: 'sync' }) : undefined
127
+ onScopeDispose(() => { cancel(); stop?.() })
128
+ return { upload, cancel, uploading, reference }
129
+ }
130
+
131
+ /**
132
+ * Resolve an asset reference to a public display URL. Public-by-default means
133
+ * no server round-trip and no expiry: the URL is deterministic from the asset id.
134
+ */
135
+ export function useAssetUrl(source: MaybeRefOrGetter<AssetDeliveryRequest | undefined>) {
136
+ const client = inject(ASSET_CLIENT_KEY, undefined)
137
+ const url = ref<string>()
138
+ const error = ref(false)
139
+
140
+ watch(() => {
141
+ const reference = toValue(source)
142
+ return reference ? `${reference.asset_id}:${reference.representation ?? 'original'}` : ''
143
+ }, () => {
144
+ const reference = toValue(source)
145
+ if (!reference) { url.value = undefined; error.value = false; return }
146
+ if (!client) { url.value = undefined; error.value = true; return }
147
+ url.value = client.assetUrl(reference, reference.representation)
148
+ error.value = false
149
+ }, { immediate: true })
150
+
151
+ return { url, error }
152
+ }
153
+
154
+ /**
155
+ * @deprecated Backward-compatible alias for ``useAssetUrl``. Public assets have
156
+ * no expiry, so the returned URL never needs refreshing; ``onError`` is a no-op
157
+ * retry hook kept for callers that expected the old grant-refresh contract.
158
+ */
159
+ export function useAssetDelivery(source: MaybeRefOrGetter<AssetDeliveryRequest | undefined>) {
160
+ const { url, error } = useAssetUrl(source)
161
+ return { url, error, onError: () => { error.value = true } }
162
+ }
@@ -0,0 +1,113 @@
1
+ <script setup lang="ts">
2
+ import type { VirtualElement } from '@floating-ui/dom'
3
+ import type { AlignedPlacement, AnchorPoint, DropdownItem } from './Dropdown.types'
4
+ import { computed, ref, useSlots } from 'vue'
5
+ import Dropdown from './Dropdown.vue'
6
+
7
+ defineOptions({ inheritAttrs: false, name: 'BglContextMenu' })
8
+
9
+ const props = withDefaults(defineProps<{
10
+ /** Declarative menu items. */
11
+ items?: DropdownItem[]
12
+ /** Optional header title shown at the top of the context menu. */
13
+ title?: string
14
+ /** Explicit viewport anchor `{ x, y, width?, height? }` for controlled mode. */
15
+ anchorPoint?: AnchorPoint | null
16
+ /** External reference element or VirtualElement. */
17
+ referenceEl?: Element | VirtualElement | null
18
+ placement?: AlignedPlacement
19
+ popupClass?: string
20
+ autoHide?: boolean
21
+ disabled?: boolean
22
+ }>(), {
23
+ placement: 'bottom-start',
24
+ autoHide: true,
25
+ disabled: false,
26
+ })
27
+
28
+ const emit = defineEmits<{
29
+ show: []
30
+ hide: []
31
+ select: [value: string | number | DropdownItem, item: DropdownItem]
32
+ }>()
33
+
34
+ const shown = defineModel('shown', { type: Boolean, default: false })
35
+ const slots = useSlots()
36
+ const dropdownRef = ref<InstanceType<typeof Dropdown> | null>(null)
37
+ const internalPoint = ref<AnchorPoint>({ x: 0, y: 0 })
38
+
39
+ const hasTargetSlot = computed(() => Boolean(slots.target))
40
+ const effectiveAnchorPoint = computed<AnchorPoint | null>(() => {
41
+ if (props.anchorPoint) return props.anchorPoint
42
+ if (props.referenceEl) return null
43
+ return internalPoint.value
44
+ })
45
+
46
+ const effectiveItems = computed<DropdownItem[]>(() => {
47
+ if (!props.items?.length) return []
48
+ if (props.title) {
49
+ return [{ header: props.title }, ...props.items]
50
+ }
51
+ return props.items
52
+ })
53
+
54
+ function openAt(target: AnchorPoint | MouseEvent) {
55
+ if (props.disabled) return
56
+ if ('clientX' in target && 'clientY' in target) {
57
+ internalPoint.value = { x: target.clientX, y: target.clientY, width: 0, height: 0 }
58
+ } else {
59
+ internalPoint.value = { ...target }
60
+ }
61
+ dropdownRef.value?.openAt(internalPoint.value)
62
+ }
63
+
64
+ function onTargetContextMenu(e: MouseEvent) {
65
+ if (props.disabled) return
66
+ e.preventDefault()
67
+ openAt(e)
68
+ }
69
+
70
+ function show() {
71
+ dropdownRef.value?.show()
72
+ }
73
+
74
+ function hide() {
75
+ dropdownRef.value?.hide()
76
+ }
77
+
78
+ defineExpose({ openAt, show, hide, shown })
79
+ </script>
80
+
81
+ <template>
82
+ <div
83
+ v-if="hasTargetSlot"
84
+ v-bind="$attrs"
85
+ style="display: contents"
86
+ @contextmenu="onTargetContextMenu"
87
+ >
88
+ <slot name="target" :open-at="openAt" :hide="hide" :shown="shown" />
89
+ </div>
90
+
91
+ <Dropdown
92
+ ref="dropdownRef"
93
+ v-model:shown="shown"
94
+ :anchor-point="effectiveAnchorPoint"
95
+ :reference-el="referenceEl"
96
+ :placement="placement"
97
+ :items="effectiveItems"
98
+ :popup-class="popupClass"
99
+ :auto-hide="autoHide"
100
+ :disabled="disabled"
101
+ :triggers="[]"
102
+ @show="emit('show')"
103
+ @hide="emit('hide')"
104
+ @select="(val, item) => emit('select', val, item)"
105
+ >
106
+ <template #default="slotProps">
107
+ <div v-if="title && !effectiveItems.length" class="px-05 py-025 txt11 semi opacity-5 uppercase">
108
+ {{ title }}
109
+ </div>
110
+ <slot v-bind="slotProps" />
111
+ </template>
112
+ </Dropdown>
113
+ </template>
@@ -0,0 +1,27 @@
1
+ import type { IconType, ThemeType } from '../types'
2
+
3
+ export type Side = 'top' | 'right' | 'bottom' | 'left'
4
+ export type Alignment = 'start' | 'end'
5
+ export type AlignedPlacement = 'auto' | Side | `${Side}-${Alignment}`
6
+ export type TriggerEvent = 'click' | 'hover'
7
+
8
+ export interface AnchorPoint {
9
+ x: number
10
+ y: number
11
+ width?: number
12
+ height?: number
13
+ }
14
+
15
+ export interface DropdownItem {
16
+ label?: string
17
+ value?: string | number
18
+ icon?: IconType
19
+ color?: ThemeType
20
+ danger?: boolean
21
+ disabled?: boolean
22
+ active?: boolean
23
+ divider?: boolean
24
+ header?: string
25
+ class?: string
26
+ action?: () => void
27
+ }