@atlassian/clientside-extensions 2.4.0-e0cce94-kuewz5ow

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 (122) hide show
  1. package/LICENSE.txt +30 -0
  2. package/README.md +7 -0
  3. package/dist/cjs/AbstractExtension.js +22 -0
  4. package/dist/cjs/AbstractExtension.js.map +1 -0
  5. package/dist/cjs/AsyncPanelExtension.js +19 -0
  6. package/dist/cjs/AsyncPanelExtension.js.map +1 -0
  7. package/dist/cjs/AsyncPanelExtension.test.js +121 -0
  8. package/dist/cjs/AsyncPanelExtension.test.js.map +1 -0
  9. package/dist/cjs/ButtonExtension.js +13 -0
  10. package/dist/cjs/ButtonExtension.js.map +1 -0
  11. package/dist/cjs/ButtonExtension.test.js +49 -0
  12. package/dist/cjs/ButtonExtension.test.js.map +1 -0
  13. package/dist/cjs/LinkExtension.js +14 -0
  14. package/dist/cjs/LinkExtension.js.map +1 -0
  15. package/dist/cjs/LinkExtension.test.js +49 -0
  16. package/dist/cjs/LinkExtension.test.js.map +1 -0
  17. package/dist/cjs/ModalExtension.js +121 -0
  18. package/dist/cjs/ModalExtension.js.map +1 -0
  19. package/dist/cjs/ModalExtension.test.js +121 -0
  20. package/dist/cjs/ModalExtension.test.js.map +1 -0
  21. package/dist/cjs/PageExtension.js +13 -0
  22. package/dist/cjs/PageExtension.js.map +1 -0
  23. package/dist/cjs/PageExtension.test.js +34 -0
  24. package/dist/cjs/PageExtension.test.js.map +1 -0
  25. package/dist/cjs/PanelExtension.js +36 -0
  26. package/dist/cjs/PanelExtension.js.map +1 -0
  27. package/dist/cjs/PanelExtension.test.js +112 -0
  28. package/dist/cjs/PanelExtension.test.js.map +1 -0
  29. package/dist/cjs/SectionExtension.js +13 -0
  30. package/dist/cjs/SectionExtension.js.map +1 -0
  31. package/dist/cjs/SectionExtension.test.js +46 -0
  32. package/dist/cjs/SectionExtension.test.js.map +1 -0
  33. package/dist/cjs/extension-type.js +15 -0
  34. package/dist/cjs/extension-type.js.map +1 -0
  35. package/dist/cjs/index.js +21 -0
  36. package/dist/cjs/index.js.map +1 -0
  37. package/dist/esm/AbstractExtension.js +18 -0
  38. package/dist/esm/AbstractExtension.js.map +1 -0
  39. package/dist/esm/AsyncPanelExtension.js +16 -0
  40. package/dist/esm/AsyncPanelExtension.js.map +1 -0
  41. package/dist/esm/AsyncPanelExtension.test.js +118 -0
  42. package/dist/esm/AsyncPanelExtension.test.js.map +1 -0
  43. package/dist/esm/ButtonExtension.js +10 -0
  44. package/dist/esm/ButtonExtension.js.map +1 -0
  45. package/dist/esm/ButtonExtension.test.js +46 -0
  46. package/dist/esm/ButtonExtension.test.js.map +1 -0
  47. package/dist/esm/LinkExtension.js +11 -0
  48. package/dist/esm/LinkExtension.js.map +1 -0
  49. package/dist/esm/LinkExtension.test.js +46 -0
  50. package/dist/esm/LinkExtension.test.js.map +1 -0
  51. package/dist/esm/ModalExtension.js +117 -0
  52. package/dist/esm/ModalExtension.js.map +1 -0
  53. package/dist/esm/ModalExtension.test.js +118 -0
  54. package/dist/esm/ModalExtension.test.js.map +1 -0
  55. package/dist/esm/PageExtension.js +10 -0
  56. package/dist/esm/PageExtension.js.map +1 -0
  57. package/dist/esm/PageExtension.test.js +31 -0
  58. package/dist/esm/PageExtension.test.js.map +1 -0
  59. package/dist/esm/PanelExtension.js +32 -0
  60. package/dist/esm/PanelExtension.js.map +1 -0
  61. package/dist/esm/PanelExtension.test.js +109 -0
  62. package/dist/esm/PanelExtension.test.js.map +1 -0
  63. package/dist/esm/SectionExtension.js +10 -0
  64. package/dist/esm/SectionExtension.js.map +1 -0
  65. package/dist/esm/SectionExtension.test.js +43 -0
  66. package/dist/esm/SectionExtension.test.js.map +1 -0
  67. package/dist/esm/extension-type.js +12 -0
  68. package/dist/esm/extension-type.js.map +1 -0
  69. package/dist/esm/index.js +10 -0
  70. package/dist/esm/index.js.map +1 -0
  71. package/dist/types/AbstractExtension.d.ts +11 -0
  72. package/dist/types/AbstractExtension.d.ts.map +1 -0
  73. package/dist/types/AsyncPanelExtension.d.ts +18 -0
  74. package/dist/types/AsyncPanelExtension.d.ts.map +1 -0
  75. package/dist/types/AsyncPanelExtension.test.d.ts +2 -0
  76. package/dist/types/AsyncPanelExtension.test.d.ts.map +1 -0
  77. package/dist/types/ButtonExtension.d.ts +10 -0
  78. package/dist/types/ButtonExtension.d.ts.map +1 -0
  79. package/dist/types/ButtonExtension.test.d.ts +2 -0
  80. package/dist/types/ButtonExtension.test.d.ts.map +1 -0
  81. package/dist/types/LinkExtension.d.ts +11 -0
  82. package/dist/types/LinkExtension.d.ts.map +1 -0
  83. package/dist/types/LinkExtension.test.d.ts +2 -0
  84. package/dist/types/LinkExtension.test.d.ts.map +1 -0
  85. package/dist/types/ModalExtension.d.ts +60 -0
  86. package/dist/types/ModalExtension.d.ts.map +1 -0
  87. package/dist/types/ModalExtension.test.d.ts +2 -0
  88. package/dist/types/ModalExtension.test.d.ts.map +1 -0
  89. package/dist/types/PageExtension.d.ts +11 -0
  90. package/dist/types/PageExtension.d.ts.map +1 -0
  91. package/dist/types/PageExtension.test.d.ts +5 -0
  92. package/dist/types/PageExtension.test.d.ts.map +1 -0
  93. package/dist/types/PanelExtension.d.ts +19 -0
  94. package/dist/types/PanelExtension.d.ts.map +1 -0
  95. package/dist/types/PanelExtension.test.d.ts +2 -0
  96. package/dist/types/PanelExtension.test.d.ts.map +1 -0
  97. package/dist/types/SectionExtension.d.ts +8 -0
  98. package/dist/types/SectionExtension.d.ts.map +1 -0
  99. package/dist/types/SectionExtension.test.d.ts +2 -0
  100. package/dist/types/SectionExtension.test.d.ts.map +1 -0
  101. package/dist/types/extension-type.d.ts +10 -0
  102. package/dist/types/extension-type.d.ts.map +1 -0
  103. package/dist/types/index.d.ts +11 -0
  104. package/dist/types/index.d.ts.map +1 -0
  105. package/lib/AbstractExtension.ts +31 -0
  106. package/lib/AsyncPanelExtension.test.ts +145 -0
  107. package/lib/AsyncPanelExtension.ts +34 -0
  108. package/lib/ButtonExtension.test.ts +61 -0
  109. package/lib/ButtonExtension.ts +20 -0
  110. package/lib/LinkExtension.test.ts +61 -0
  111. package/lib/LinkExtension.ts +22 -0
  112. package/lib/ModalExtension.test.ts +147 -0
  113. package/lib/ModalExtension.ts +188 -0
  114. package/lib/PageExtension.test.ts +38 -0
  115. package/lib/PageExtension.ts +21 -0
  116. package/lib/PanelExtension.test.ts +134 -0
  117. package/lib/PanelExtension.ts +51 -0
  118. package/lib/SectionExtension.test.ts +57 -0
  119. package/lib/SectionExtension.ts +18 -0
  120. package/lib/extension-type.ts +10 -0
  121. package/lib/index.ts +21 -0
  122. package/package.json +79 -0
@@ -0,0 +1,11 @@
1
+ import type { ExtensionAttributes, ExtensionAttributesProvider, OnAction } from '@atlassian/clientside-extensions-registry';
2
+ import { ExtensionType } from './extension-type';
3
+ export interface LinkAttributes extends ExtensionAttributes {
4
+ onAction?: OnAction;
5
+ url: string;
6
+ label: string;
7
+ type?: ExtensionType.link;
8
+ }
9
+ export declare type LinkAttributesProvider<ContextT> = ExtensionAttributesProvider<LinkAttributes, ContextT>;
10
+ export declare const factory: <ContextT>(provider: ExtensionAttributesProvider<LinkAttributes, ContextT>) => ExtensionAttributesProvider<LinkAttributes, ContextT>;
11
+ //# sourceMappingURL=LinkExtension.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LinkExtension.d.ts","sourceRoot":"","sources":["../../lib/LinkExtension.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,2BAA2B,EAAE,QAAQ,EAAE,MAAM,2CAA2C,CAAC;AAE5H,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD,MAAM,WAAW,cAAe,SAAQ,mBAAmB;IACvD,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,aAAa,CAAC,IAAI,CAAC;CAC7B;AAED,oBAAY,sBAAsB,CAAC,QAAQ,IAAI,2BAA2B,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC;AAGrG,eAAO,MAAM,OAAO,sIAOnB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=LinkExtension.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LinkExtension.test.d.ts","sourceRoot":"","sources":["../../lib/LinkExtension.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,60 @@
1
+ import type { ExtensionAttributes, ExtensionAttributesProvider } from '@atlassian/clientside-extensions-registry';
2
+ import type { Dispatch as ReactDispatch, KeyboardEvent as ReactKeyboardEvent, MouseEvent as ReactMouseEvent, SetStateAction as ReactSetStateAction } from 'react';
3
+ import { ExtensionType } from './extension-type';
4
+ import type { LifecycleCallback, MountableExtension } from './AbstractExtension';
5
+ declare type KeyboardOrMouseEvent = ReactMouseEvent<HTMLElement> | ReactKeyboardEvent<HTMLElement> | KeyboardEvent;
6
+ interface ModalCloseCallback {
7
+ (e: KeyboardOrMouseEvent): boolean | void;
8
+ }
9
+ export declare type ModalAction = {
10
+ text: string;
11
+ onClick: () => void;
12
+ isDisabled?: boolean;
13
+ isLoading?: boolean;
14
+ testId?: string;
15
+ };
16
+ export declare type ModalRenderExtension = (api: Api) => void;
17
+ export interface ModalAttributes extends ExtensionAttributes {
18
+ onAction: ModalRenderExtension;
19
+ label: string;
20
+ type?: ExtensionType.modal;
21
+ }
22
+ export declare type ModalAttributesProvider<ContextT> = ExtensionAttributesProvider<ModalAttributes, ContextT>;
23
+ export declare const factory: <ContextT>(provider: ExtensionAttributesProvider<ModalAttributes, ContextT>) => ExtensionAttributesProvider<ModalAttributes, ContextT>;
24
+ export declare enum Appearance {
25
+ 'danger' = "danger",
26
+ 'warning' = "warning"
27
+ }
28
+ export declare enum Width {
29
+ 'small' = "small",
30
+ 'medium' = "medium",
31
+ 'large' = "large",
32
+ 'x-large' = "x-large"
33
+ }
34
+ export declare class Api implements MountableExtension {
35
+ private title;
36
+ private width;
37
+ private appearance;
38
+ private renderCallback;
39
+ private cleanupCallback;
40
+ private readonly closeModalFn;
41
+ private onCloseCallback;
42
+ constructor(closeModalFn: () => void, setActions: ReactDispatch<ReactSetStateAction<ModalAction[]>>);
43
+ setTitle: (title: string) => this;
44
+ setWidth: (width: Width) => this;
45
+ setAppearance: (appearance: Appearance) => this;
46
+ onMount: (callback: LifecycleCallback) => this;
47
+ onUnmount: (callback: LifecycleCallback) => this;
48
+ closeModal: () => void;
49
+ getTitle(): string;
50
+ getWidth(): Width;
51
+ getAppearance(): Appearance;
52
+ getRenderCallback(): LifecycleCallback;
53
+ getCleanupCallback(): LifecycleCallback;
54
+ setActions: (actions: ModalAction[]) => void;
55
+ onClose(callback: ModalCloseCallback): this;
56
+ getOnCloseCallback(): ModalCloseCallback;
57
+ static filterActionProps(actions: unknown[]): ModalAction[];
58
+ }
59
+ export {};
60
+ //# sourceMappingURL=ModalExtension.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ModalExtension.d.ts","sourceRoot":"","sources":["../../lib/ModalExtension.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,2BAA2B,EAAE,MAAM,2CAA2C,CAAC;AAElH,OAAO,KAAK,EACR,QAAQ,IAAI,aAAa,EACzB,aAAa,IAAI,kBAAkB,EACnC,UAAU,IAAI,eAAe,EAC7B,cAAc,IAAI,mBAAmB,EAExC,MAAM,OAAO,CAAC;AAEf,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,KAAK,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAIjF,aAAK,oBAAoB,GAAG,eAAe,CAAC,WAAW,CAAC,GAAG,kBAAkB,CAAC,WAAW,CAAC,GAAG,aAAa,CAAC;AAE3G,UAAU,kBAAkB;IACxB,CAAC,CAAC,EAAE,oBAAoB,GAAG,OAAO,GAAG,IAAI,CAAC;CAC7C;AAED,oBAAY,WAAW,GAAG;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,oBAAY,oBAAoB,GAAG,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,CAAC;AAEtD,MAAM,WAAW,eAAgB,SAAQ,mBAAmB;IACxD,QAAQ,EAAE,oBAAoB,CAAC;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,aAAa,CAAC,KAAK,CAAC;CAC9B;AAED,oBAAY,uBAAuB,CAAC,QAAQ,IAAI,2BAA2B,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC;AAEvG,eAAO,MAAM,OAAO,wIAQnB,CAAC;AAIF,oBAAY,UAAU;IAClB,QAAQ,WAAW;IACnB,SAAS,YAAY;CACxB;AAED,oBAAY,KAAK;IACb,OAAO,UAAU;IACjB,QAAQ,WAAW;IACnB,OAAO,UAAU;IACjB,SAAS,YAAY;CACxB;AAED,qBAAa,GAAI,YAAW,kBAAkB;IAC1C,OAAO,CAAC,KAAK,CAAM;IAEnB,OAAO,CAAC,KAAK,CAAS;IAEtB,OAAO,CAAC,UAAU,CAAc;IAEhC,OAAO,CAAC,cAAc,CAA2B;IAEjD,OAAO,CAAC,eAAe,CAA2B;IAElD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAoB;IAEjD,OAAO,CAAC,eAAe,CAAkC;gBAE7C,YAAY,EAAE,MAAM,IAAI,EAAE,UAAU,EAAE,aAAa,CAAC,mBAAmB,CAAC,WAAW,EAAE,CAAC,CAAC;IAU5F,QAAQ,UAAW,MAAM,UAI9B;IAEK,QAAQ,UAAW,KAAK,UAgB7B;IAEK,aAAa,eAAgB,UAAU,UAgB5C;IAEK,OAAO,aAAc,iBAAiB,UAI3C;IAEK,SAAS,aAAc,iBAAiB,UAI7C;IAEK,UAAU,aAEf;IAEK,QAAQ;IAIR,QAAQ;IAIR,aAAa;IAIb,iBAAiB;IAIjB,kBAAkB;IAIlB,UAAU,EAAE,CAAC,OAAO,EAAE,WAAW,EAAE,KAAK,IAAI,CAAC;IAE7C,OAAO,CAAC,QAAQ,EAAE,kBAAkB;IAMpC,kBAAkB;IAIzB,MAAM,CAAC,iBAAiB,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,WAAW,EAAE;CAS9D"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ModalExtension.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ModalExtension.test.d.ts","sourceRoot":"","sources":["../../lib/ModalExtension.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,11 @@
1
+ import type { DataProviderPayload, ExtensionAttributes } from '@atlassian/clientside-extensions-registry';
2
+ import { ExtensionType } from './extension-type';
3
+ declare type RenderCallback<DataProviderT> = (node: HTMLElement, data: DataProviderPayload<DataProviderT>) => void;
4
+ export interface PageAttributes<DataProviderT> extends ExtensionAttributes {
5
+ onAction: RenderCallback<DataProviderT>;
6
+ type: ExtensionType.page;
7
+ }
8
+ export declare type PageAttributesProvider<DataProviderT = unknown> = () => PageAttributes<DataProviderT>;
9
+ export declare const factory: <DataProviderT>(renderCallback: RenderCallback<DataProviderT>) => PageAttributesProvider<DataProviderT>;
10
+ export {};
11
+ //# sourceMappingURL=PageExtension.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PageExtension.d.ts","sourceRoot":"","sources":["../../lib/PageExtension.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,2CAA2C,CAAC;AAE1G,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD,aAAK,cAAc,CAAC,aAAa,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,mBAAmB,CAAC,aAAa,CAAC,KAAK,IAAI,CAAC;AAE3G,MAAM,WAAW,cAAc,CAAC,aAAa,CAAE,SAAQ,mBAAmB;IACtE,QAAQ,EAAE,cAAc,CAAC,aAAa,CAAC,CAAC;IACxC,IAAI,EAAE,aAAa,CAAC,IAAI,CAAC;CAC5B;AAED,oBAAY,sBAAsB,CAAC,aAAa,GAAG,OAAO,IAAI,MAAM,cAAc,CAAC,aAAa,CAAC,CAAC;AAElG,eAAO,MAAM,OAAO,yGAOnB,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * @jest-environment jsdom
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=PageExtension.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PageExtension.test.d.ts","sourceRoot":"","sources":["../../lib/PageExtension.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,19 @@
1
+ import type { Context, ExtensionAttributes, ExtensionAttributesProvider } from '@atlassian/clientside-extensions-registry';
2
+ import { ExtensionType } from './extension-type';
3
+ import type { LifecycleCallback, MountableExtension } from './AbstractExtension';
4
+ export declare type PanelRenderExtension = (api: Api, context?: Context<{}>, data?: unknown) => void;
5
+ export interface PanelAttributes extends ExtensionAttributes {
6
+ onAction: PanelRenderExtension;
7
+ type?: ExtensionType.panel;
8
+ }
9
+ export declare type PanelAttributesProvider<ContextT> = ExtensionAttributesProvider<PanelAttributes, ContextT>;
10
+ export declare const factory: <ContextT>(provider: ExtensionAttributesProvider<PanelAttributes, ContextT>) => ExtensionAttributesProvider<PanelAttributes, ContextT>;
11
+ export declare class Api implements MountableExtension {
12
+ private renderCallback;
13
+ private cleanupCallback;
14
+ onMount(callback: LifecycleCallback): this;
15
+ onUnmount(callback: LifecycleCallback): this;
16
+ getRenderCallback(): LifecycleCallback;
17
+ getCleanupCallback(): LifecycleCallback;
18
+ }
19
+ //# sourceMappingURL=PanelExtension.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PanelExtension.d.ts","sourceRoot":"","sources":["../../lib/PanelExtension.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,mBAAmB,EAAE,2BAA2B,EAAE,MAAM,2CAA2C,CAAC;AAE3H,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,KAAK,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAGjF,oBAAY,oBAAoB,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;AAE7F,MAAM,WAAW,eAAgB,SAAQ,mBAAmB;IACxD,QAAQ,EAAE,oBAAoB,CAAC;IAC/B,IAAI,CAAC,EAAE,aAAa,CAAC,KAAK,CAAC;CAC9B;AAED,oBAAY,uBAAuB,CAAC,QAAQ,IAAI,2BAA2B,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC;AAEvG,eAAO,MAAM,OAAO,wIAOnB,CAAC;AAIF,qBAAa,GAAI,YAAW,kBAAkB;IAC1C,OAAO,CAAC,cAAc,CAA2B;IAEjD,OAAO,CAAC,eAAe,CAA2B;IAE3C,OAAO,CAAC,QAAQ,EAAE,iBAAiB;IAMnC,SAAS,CAAC,QAAQ,EAAE,iBAAiB;IAMrC,iBAAiB;IAIjB,kBAAkB;CAG5B"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=PanelExtension.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PanelExtension.test.d.ts","sourceRoot":"","sources":["../../lib/PanelExtension.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,8 @@
1
+ import type { ExtensionAttributes, ExtensionAttributesProvider } from '@atlassian/clientside-extensions-registry';
2
+ import { ExtensionType } from './extension-type';
3
+ export interface SectionAttributes extends ExtensionAttributes {
4
+ type?: ExtensionType.section;
5
+ }
6
+ export declare type SectionAttributesProvider<ContextT> = ExtensionAttributesProvider<SectionAttributes, ContextT>;
7
+ export declare const factory: <ContextT>(provider: ExtensionAttributesProvider<SectionAttributes, ContextT>) => ExtensionAttributesProvider<SectionAttributes, ContextT>;
8
+ //# sourceMappingURL=SectionExtension.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SectionExtension.d.ts","sourceRoot":"","sources":["../../lib/SectionExtension.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,2BAA2B,EAAE,MAAM,2CAA2C,CAAC;AAElH,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD,MAAM,WAAW,iBAAkB,SAAQ,mBAAmB;IAC1D,IAAI,CAAC,EAAE,aAAa,CAAC,OAAO,CAAC;CAChC;AAED,oBAAY,yBAAyB,CAAC,QAAQ,IAAI,2BAA2B,CAAC,iBAAiB,EAAE,QAAQ,CAAC,CAAC;AAE3G,eAAO,MAAM,OAAO,4IAOnB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=SectionExtension.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SectionExtension.test.d.ts","sourceRoot":"","sources":["../../lib/SectionExtension.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,10 @@
1
+ export declare enum ExtensionType {
2
+ 'asyncPanel' = "async-panel",
3
+ button = "button",
4
+ link = "link",
5
+ modal = "modal",
6
+ panel = "panel",
7
+ page = "page",
8
+ section = "section"
9
+ }
10
+ //# sourceMappingURL=extension-type.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension-type.d.ts","sourceRoot":"","sources":["../../lib/extension-type.ts"],"names":[],"mappings":"AACA,oBAAY,aAAa;IACrB,YAAY,gBAAgB;IAC5B,MAAM,WAAW;IACjB,IAAI,SAAS;IACb,KAAK,UAAU;IACf,KAAK,UAAU;IACf,IAAI,SAAS;IACb,OAAO,YAAY;CACtB"}
@@ -0,0 +1,11 @@
1
+ import * as AsyncPanelExtension from './AsyncPanelExtension';
2
+ import * as ButtonExtension from './ButtonExtension';
3
+ import * as LinkExtension from './LinkExtension';
4
+ import * as ModalExtension from './ModalExtension';
5
+ import * as PanelExtension from './PanelExtension';
6
+ import * as SectionExtension from './SectionExtension';
7
+ import * as PageExtension from './PageExtension';
8
+ import { ExtensionType } from './extension-type';
9
+ export type { MountableExtension, LifecycleCallback } from './AbstractExtension';
10
+ export { AsyncPanelExtension, ButtonExtension, LinkExtension, ModalExtension, PanelExtension, SectionExtension, PageExtension, ExtensionType, };
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../lib/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,mBAAmB,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,eAAe,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,aAAa,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,cAAc,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,cAAc,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,gBAAgB,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,aAAa,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD,YAAY,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAEjF,OAAO,EACH,mBAAmB,EACnB,eAAe,EACf,aAAa,EACb,cAAc,EACd,cAAc,EACd,gBAAgB,EAChB,aAAa,EACb,aAAa,GAChB,CAAC"}
@@ -0,0 +1,31 @@
1
+ import { onDebug } from '@atlassian/clientside-extensions-debug';
2
+
3
+ // We are fine with any type here
4
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
5
+ type Callable = (...args: any[]) => any;
6
+
7
+ export interface LifecycleCallback {
8
+ (element: HTMLElement): void;
9
+ }
10
+
11
+ export interface MountableExtension {
12
+ onMount(mountCallback: LifecycleCallback): MountableExtension;
13
+
14
+ onUnmount(unmountCallback: LifecycleCallback): MountableExtension;
15
+ }
16
+
17
+ export function safeguard<T extends Callable>(callbackDebugName: string, callback: T): (...args: Parameters<T>) => ReturnType<T> {
18
+ return (...args: Parameters<T>) => {
19
+ let result;
20
+ try {
21
+ result = callback(...args);
22
+ } catch (e) {
23
+ onDebug(({ error }) => ({
24
+ level: error,
25
+ message: `Failed to execute ${callbackDebugName} callback.
26
+ Error: ${e}`,
27
+ }));
28
+ }
29
+ return result;
30
+ };
31
+ }
@@ -0,0 +1,145 @@
1
+ import type { ExtensionAPI } from '@atlassian/clientside-extensions-registry';
2
+ import { onDebug } from '@atlassian/clientside-extensions-debug';
3
+ import * as AsyncPanelExtension from './AsyncPanelExtension';
4
+
5
+ jest.mock('@atlassian/clientside-extensions-debug');
6
+
7
+ interface TestContext {
8
+ value?: number;
9
+ }
10
+
11
+ describe('AsyncPanelExtension', () => {
12
+ // @ts-expect-error - invalid values for contextProvider and type. Factory should overwrite them.
13
+ const testAttributesProvider: AsyncPanelExtension.AsyncPanelAttributesProvider = (api, context: TestContext) => {
14
+ api.onCleanup(jest.fn());
15
+ api.updateAttributes({});
16
+
17
+ return {
18
+ type: 'not-valid',
19
+ contextProvider: 'not-valid-context-provider',
20
+ label: context.value === 42 ? 'The meaning of life' : 'A label',
21
+ onAction: jest.fn(),
22
+ };
23
+ };
24
+
25
+ const testAPI: ExtensionAPI<typeof testAttributesProvider> = {
26
+ onCleanup: jest.fn(),
27
+ updateAttributes: jest.fn(),
28
+ };
29
+
30
+ it('should generate the extension descriptor with the correct type and contextProvider', () => {
31
+ const extensionProvider = AsyncPanelExtension.factory(testAttributesProvider);
32
+ const extension = extensionProvider(testAPI, {});
33
+
34
+ // expect all attributes to be merged, type and contextProvider to be overwritten with the correct values.
35
+ expect(extension).toEqual({
36
+ type: 'async-panel',
37
+ label: 'A label',
38
+ onAction: expect.any(Function),
39
+ contextProvider: expect.any(Function),
40
+ });
41
+ });
42
+
43
+ it('should provide a extensionAPI object to the extension provider', () => {
44
+ expect(testAPI.onCleanup).toHaveBeenCalledTimes(0);
45
+ expect(testAPI.updateAttributes).toHaveBeenCalledTimes(0);
46
+
47
+ const extensionProvider = AsyncPanelExtension.factory(testAttributesProvider);
48
+ extensionProvider(testAPI, {});
49
+
50
+ expect(testAPI.onCleanup).toHaveBeenCalledTimes(1);
51
+ expect(testAPI.updateAttributes).toHaveBeenCalledTimes(1);
52
+ });
53
+
54
+ it('should share any provided context with the attributes provider', () => {
55
+ const extensionProvider = AsyncPanelExtension.factory(testAttributesProvider);
56
+ const extension = extensionProvider(testAPI, { value: 42 });
57
+
58
+ // expect label to change because of context
59
+ expect(extension).toEqual({
60
+ type: 'async-panel',
61
+ label: 'The meaning of life',
62
+ onAction: expect.any(Function),
63
+ contextProvider: expect.any(Function),
64
+ });
65
+ });
66
+
67
+ it('should add a contextProvider method to retreive the shared context', () => {
68
+ const extensionProvider = AsyncPanelExtension.factory(testAttributesProvider);
69
+ const testContext: TestContext = { value: 42 };
70
+ const extension = extensionProvider(testAPI, testContext);
71
+
72
+ expect(extension.contextProvider()).toBe(testContext);
73
+ });
74
+
75
+ describe('API', () => {
76
+ let api: AsyncPanelExtension.Api;
77
+ const el: HTMLElement = document.createElement('div');
78
+
79
+ beforeEach(() => {
80
+ api = new AsyncPanelExtension.Api();
81
+ });
82
+
83
+ it('#onMount callback used in getRenderCallback', () => {
84
+ const cb = jest.fn();
85
+ api.onMount(cb);
86
+ api.getRenderCallback()(el);
87
+ expect(cb).toHaveBeenCalledTimes(1);
88
+ });
89
+
90
+ it('#onMount does nothing if not set', () => {
91
+ expect(() => {
92
+ api.getRenderCallback()(el);
93
+ }).not.toThrow();
94
+ });
95
+
96
+ it('#onMount does nothing if callback is not function', () => {
97
+ // @ts-expect-error checking that non-TS consumers don't shoot themselves (or others) in the foot
98
+ api.onMount(null);
99
+ expect(() => {
100
+ api.getRenderCallback()(el);
101
+ }).not.toThrow();
102
+ });
103
+
104
+ it('#onMount fails gracefully if callback throws error', () => {
105
+ api.onMount(() => {
106
+ throw Error('whoops');
107
+ });
108
+ expect(() => {
109
+ api.getRenderCallback()(el);
110
+ }).not.toThrow();
111
+ });
112
+
113
+ it('#onUnmount callback used in getCleanupCallback', () => {
114
+ const cb = jest.fn();
115
+ api.onUnmount(cb);
116
+ api.getCleanupCallback()(el);
117
+ expect(cb).toHaveBeenCalledTimes(1);
118
+ });
119
+
120
+ it('#onUnmount does nothing if not set', () => {
121
+ expect(() => {
122
+ api.getCleanupCallback()(el);
123
+ }).not.toThrow();
124
+ });
125
+
126
+ it('#onUnmount does nothing if callback is not function', () => {
127
+ // @ts-expect-error checking that non-TS consumers don't shoot themselves (or others) in the foot
128
+ api.onUnmount(null);
129
+ expect(() => {
130
+ api.getCleanupCallback()(el);
131
+ }).not.toThrow();
132
+ expect(onDebug).toHaveBeenCalledTimes(1);
133
+ });
134
+
135
+ it('#onUnmount fails gracefully if callback throws error', () => {
136
+ api.onUnmount(() => {
137
+ throw Error('whoops');
138
+ });
139
+ expect(() => {
140
+ api.getCleanupCallback()(el);
141
+ }).not.toThrow();
142
+ expect(onDebug).toHaveBeenCalledTimes(1);
143
+ });
144
+ });
145
+ });
@@ -0,0 +1,34 @@
1
+ import type { ExtensionAttributes, ExtensionAttributesProvider, Context } from '@atlassian/clientside-extensions-registry';
2
+ import type { PanelRenderExtension } from './PanelExtension';
3
+ import { Api } from './PanelExtension';
4
+ import { ExtensionType } from './extension-type';
5
+
6
+ export interface AsyncPanelRenderExtension extends PanelRenderExtension {}
7
+
8
+ export interface AsyncPanelAttributes extends ExtensionAttributes {
9
+ onAction: AsyncPanelRenderExtension;
10
+ type?: ExtensionType.asyncPanel;
11
+ }
12
+
13
+ export type AsyncPanelAttributesProvider<ContextT> = ExtensionAttributesProvider<AsyncPanelAttributes, ContextT>;
14
+
15
+ export interface AsyncPanelAttributesWithContext extends AsyncPanelAttributes {
16
+ contextProvider: () => Context<{}>;
17
+ }
18
+
19
+ export type AsyncPanelAttributesProviderWithContext<ContextT> = ExtensionAttributesProvider<AsyncPanelAttributesWithContext, ContextT>;
20
+
21
+ export const factory = <ContextT>(provider: AsyncPanelAttributesProvider<ContextT>): AsyncPanelAttributesProviderWithContext<ContextT> => {
22
+ return (extensionApi, context): AsyncPanelAttributesWithContext => {
23
+ return {
24
+ ...provider(extensionApi, context),
25
+ // We are passing the context provider function reference into the <AsyncPanelHandler.AsyncPanelRenderer> component
26
+ contextProvider() {
27
+ return context;
28
+ },
29
+ type: ExtensionType.asyncPanel,
30
+ };
31
+ };
32
+ };
33
+
34
+ export { Api };
@@ -0,0 +1,61 @@
1
+ import type { ExtensionAPI } from '@atlassian/clientside-extensions-registry';
2
+ import * as ButtonExtension from './ButtonExtension';
3
+ import type { ButtonAttributesProvider } from './ButtonExtension';
4
+
5
+ interface TestContext {
6
+ value?: number;
7
+ }
8
+
9
+ describe('ButtonExtension', () => {
10
+ // @ts-expect-error We set the invalid type
11
+ const testAttributesProvider: ButtonAttributesProvider = (api, context: TestContext) => {
12
+ api.onCleanup(jest.fn());
13
+ api.updateAttributes({});
14
+
15
+ return {
16
+ type: 'not-valid',
17
+ label: context.value === 42 ? 'The meaning of life' : 'A label',
18
+ onAction: jest.fn(),
19
+ };
20
+ };
21
+
22
+ const testAPI: ExtensionAPI<typeof testAttributesProvider> = {
23
+ onCleanup: jest.fn(),
24
+ updateAttributes: jest.fn(),
25
+ };
26
+
27
+ it('should generate the extension descriptor with the correct type', () => {
28
+ const extensionProvider = ButtonExtension.factory(testAttributesProvider);
29
+ const extension = extensionProvider(testAPI, {});
30
+
31
+ // expect all atributes to be merged, and type to be overwritten with the correct value.
32
+ expect(extension).toEqual({
33
+ type: 'button',
34
+ label: 'A label',
35
+ onAction: expect.any(Function),
36
+ });
37
+ });
38
+
39
+ it('should provide a extensionAPI object to the extension provider', () => {
40
+ expect(testAPI.onCleanup).toHaveBeenCalledTimes(0);
41
+ expect(testAPI.updateAttributes).toHaveBeenCalledTimes(0);
42
+
43
+ const extensionProvider = ButtonExtension.factory(testAttributesProvider);
44
+ extensionProvider(testAPI, {});
45
+
46
+ expect(testAPI.onCleanup).toHaveBeenCalledTimes(1);
47
+ expect(testAPI.updateAttributes).toHaveBeenCalledTimes(1);
48
+ });
49
+
50
+ it('should share any provided context with the attributes provider', () => {
51
+ const extensionProvider = ButtonExtension.factory(testAttributesProvider);
52
+ const extension = extensionProvider(testAPI, { value: 42 });
53
+
54
+ // expect label to change because of context
55
+ expect(extension).toEqual({
56
+ type: 'button',
57
+ label: 'The meaning of life',
58
+ onAction: expect.any(Function),
59
+ });
60
+ });
61
+ });
@@ -0,0 +1,20 @@
1
+ import type { ExtensionAttributes, ExtensionAttributesProvider, OnAction } from '@atlassian/clientside-extensions-registry';
2
+
3
+ import { ExtensionType } from './extension-type';
4
+
5
+ export interface ButtonAttributes extends ExtensionAttributes {
6
+ onAction?: OnAction;
7
+ label: string;
8
+ type?: ExtensionType.button;
9
+ }
10
+
11
+ export type ButtonAttributesProvider<ContextT> = ExtensionAttributesProvider<ButtonAttributes, ContextT>;
12
+
13
+ export const factory = <ContextT>(provider: ButtonAttributesProvider<ContextT>): ButtonAttributesProvider<ContextT> => {
14
+ return (...args) => {
15
+ return {
16
+ ...provider(...args),
17
+ type: ExtensionType.button,
18
+ };
19
+ };
20
+ };
@@ -0,0 +1,61 @@
1
+ import type { ExtensionAPI } from '@atlassian/clientside-extensions-registry';
2
+ import * as LinkExtension from './LinkExtension';
3
+ import type { LinkAttributesProvider } from './LinkExtension';
4
+
5
+ interface TestContext {
6
+ value?: number;
7
+ }
8
+
9
+ describe('LinkExtension', () => {
10
+ // @ts-expect-error we set the invalid type
11
+ const testAttributesProvider: LinkAttributesProvider = (api, context: TestContext) => {
12
+ api.onCleanup(jest.fn());
13
+ api.updateAttributes({});
14
+
15
+ return {
16
+ type: 'not-valid',
17
+ label: context.value === 42 ? 'The meaning of life' : 'A label',
18
+ link: 'https://go.atlassian.com/clientside-extensions',
19
+ };
20
+ };
21
+
22
+ const testAPI: ExtensionAPI<typeof testAttributesProvider> = {
23
+ onCleanup: jest.fn(),
24
+ updateAttributes: jest.fn(),
25
+ };
26
+
27
+ it('should generate the extension descriptor with the correct type', () => {
28
+ const extensionProvider = LinkExtension.factory(testAttributesProvider);
29
+ const extension = extensionProvider(testAPI, {});
30
+
31
+ // expect all attributes to be merged, and type to be overwritten with the correct value.
32
+ expect(extension).toEqual({
33
+ type: 'link',
34
+ label: 'A label',
35
+ link: 'https://go.atlassian.com/clientside-extensions',
36
+ });
37
+ });
38
+
39
+ it('should provide a extensionAPI object to the extension provider', () => {
40
+ expect(testAPI.onCleanup).toHaveBeenCalledTimes(0);
41
+ expect(testAPI.updateAttributes).toHaveBeenCalledTimes(0);
42
+
43
+ const extensionProvider = LinkExtension.factory(testAttributesProvider);
44
+ extensionProvider(testAPI, {});
45
+
46
+ expect(testAPI.onCleanup).toHaveBeenCalledTimes(1);
47
+ expect(testAPI.updateAttributes).toHaveBeenCalledTimes(1);
48
+ });
49
+
50
+ it('should share any provided context with the attributes provider', () => {
51
+ const extensionProvider = LinkExtension.factory(testAttributesProvider);
52
+ const extension = extensionProvider(testAPI, { value: 42 });
53
+
54
+ // expect label to change because of context
55
+ expect(extension).toEqual({
56
+ type: 'link',
57
+ label: 'The meaning of life',
58
+ link: 'https://go.atlassian.com/clientside-extensions',
59
+ });
60
+ });
61
+ });
@@ -0,0 +1,22 @@
1
+ import type { ExtensionAttributes, ExtensionAttributesProvider, OnAction } from '@atlassian/clientside-extensions-registry';
2
+
3
+ import { ExtensionType } from './extension-type';
4
+
5
+ export interface LinkAttributes extends ExtensionAttributes {
6
+ onAction?: OnAction;
7
+ url: string;
8
+ label: string;
9
+ type?: ExtensionType.link;
10
+ }
11
+
12
+ export type LinkAttributesProvider<ContextT> = ExtensionAttributesProvider<LinkAttributes, ContextT>;
13
+
14
+ // eslint-disable-next-line import/prefer-default-export
15
+ export const factory = <ContextT>(provider: LinkAttributesProvider<ContextT>): LinkAttributesProvider<ContextT> => {
16
+ return (...args) => {
17
+ return {
18
+ ...provider(...args),
19
+ type: ExtensionType.link,
20
+ };
21
+ };
22
+ };