@frontify/guideline-blocks-settings 0.27.0 → 0.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (214) hide show
  1. package/.eslintrc.js +1 -1
  2. package/CHANGELOG.md +15 -0
  3. package/README.md +24 -5
  4. package/package.json +46 -10
  5. package/postcss.config.js +8 -0
  6. package/setupTests.ts +13 -0
  7. package/src/components/Attachments/AttachmentItem.tsx +257 -0
  8. package/src/components/Attachments/Attachments.spec.ct.tsx +151 -0
  9. package/src/components/Attachments/Attachments.tsx +221 -0
  10. package/src/components/Attachments/index.ts +4 -0
  11. package/src/components/Attachments/types.ts +30 -0
  12. package/src/components/BlockInjectButton/BlockInjectButton.spec.ct.tsx +48 -0
  13. package/src/components/BlockInjectButton/BlockInjectButton.tsx +212 -0
  14. package/src/components/BlockInjectButton/index.ts +4 -0
  15. package/src/components/BlockInjectButton/types.ts +18 -0
  16. package/src/components/BlockItemWrapper/BlockItemWrapper.spec.ct.tsx +146 -0
  17. package/src/components/BlockItemWrapper/BlockItemWrapper.tsx +76 -0
  18. package/src/components/BlockItemWrapper/Toolbar.tsx +128 -0
  19. package/src/components/BlockItemWrapper/constants.ts +4 -0
  20. package/src/components/BlockItemWrapper/index.ts +5 -0
  21. package/src/components/BlockItemWrapper/types.ts +46 -0
  22. package/src/components/DownloadButton/DownloadButton.spec.ct.tsx +20 -0
  23. package/src/components/DownloadButton/DownloadButton.tsx +36 -0
  24. package/src/components/DownloadButton/index.ts +3 -0
  25. package/src/components/DownloadButton/types.ts +5 -0
  26. package/src/components/RichTextEditor/RichTextEditor.spec.ct.tsx +204 -0
  27. package/src/components/RichTextEditor/RichTextEditor.tsx +62 -0
  28. package/src/components/RichTextEditor/SerializedText.tsx +25 -0
  29. package/src/components/RichTextEditor/constants.ts +3 -0
  30. package/src/components/RichTextEditor/index.ts +6 -0
  31. package/src/components/RichTextEditor/pluginPresets/defaultPluginsWithLinkChooser.tsx +53 -0
  32. package/src/components/RichTextEditor/pluginPresets/index.ts +3 -0
  33. package/src/components/RichTextEditor/plugins/ButtonPlugin/ButtonMarkupElement/ButtonMarkupElementNode.tsx +74 -0
  34. package/src/components/RichTextEditor/plugins/ButtonPlugin/ButtonMarkupElement/index.ts +11 -0
  35. package/src/components/RichTextEditor/plugins/ButtonPlugin/components/ButtonButton.tsx +20 -0
  36. package/src/components/RichTextEditor/plugins/ButtonPlugin/components/ButtonToolbarButton.tsx +56 -0
  37. package/src/components/RichTextEditor/plugins/ButtonPlugin/components/FloatingButton/CustomFloatingButton.tsx +19 -0
  38. package/src/components/RichTextEditor/plugins/ButtonPlugin/components/FloatingButton/EditButtonModal/EditModal.tsx +42 -0
  39. package/src/components/RichTextEditor/plugins/ButtonPlugin/components/FloatingButton/FloatingButton.tsx +37 -0
  40. package/src/components/RichTextEditor/plugins/ButtonPlugin/components/FloatingButton/FloatingButtonEditButton.tsx +22 -0
  41. package/src/components/RichTextEditor/plugins/ButtonPlugin/components/FloatingButton/FloatingButtonUrlInput.tsx +30 -0
  42. package/src/components/RichTextEditor/plugins/ButtonPlugin/components/FloatingButton/InsertButtonModal/InsertButtonModal.tsx +81 -0
  43. package/src/components/RichTextEditor/plugins/ButtonPlugin/components/FloatingButton/InsertButtonModal/types.ts +13 -0
  44. package/src/components/RichTextEditor/plugins/ButtonPlugin/components/FloatingButton/InsertButtonModal/useInsertModal.ts +143 -0
  45. package/src/components/RichTextEditor/plugins/ButtonPlugin/components/FloatingButton/UnlinkButton.tsx +31 -0
  46. package/src/components/RichTextEditor/plugins/ButtonPlugin/components/FloatingButton/floatingButtonStore.ts +46 -0
  47. package/src/components/RichTextEditor/plugins/ButtonPlugin/components/FloatingButton/index.ts +12 -0
  48. package/src/components/RichTextEditor/plugins/ButtonPlugin/components/FloatingButton/useFloatingButtonEdit.ts +113 -0
  49. package/src/components/RichTextEditor/plugins/ButtonPlugin/components/FloatingButton/useFloatingButtonEnter.ts +21 -0
  50. package/src/components/RichTextEditor/plugins/ButtonPlugin/components/FloatingButton/useFloatingButtonEscape.ts +30 -0
  51. package/src/components/RichTextEditor/plugins/ButtonPlugin/components/FloatingButton/useFloatingButtonInsert.ts +71 -0
  52. package/src/components/RichTextEditor/plugins/ButtonPlugin/components/FloatingButton/useVirtualFloatingButton.ts +22 -0
  53. package/src/components/RichTextEditor/plugins/ButtonPlugin/components/index.ts +3 -0
  54. package/src/components/RichTextEditor/plugins/ButtonPlugin/createButtonPlugin.ts +116 -0
  55. package/src/components/RichTextEditor/plugins/ButtonPlugin/index.ts +7 -0
  56. package/src/components/RichTextEditor/plugins/ButtonPlugin/transforms/index.ts +8 -0
  57. package/src/components/RichTextEditor/plugins/ButtonPlugin/transforms/insertButton.ts +17 -0
  58. package/src/components/RichTextEditor/plugins/ButtonPlugin/transforms/submitFloatingButton.ts +40 -0
  59. package/src/components/RichTextEditor/plugins/ButtonPlugin/transforms/unwrapButton.ts +68 -0
  60. package/src/components/RichTextEditor/plugins/ButtonPlugin/transforms/upsertButton.ts +198 -0
  61. package/src/components/RichTextEditor/plugins/ButtonPlugin/transforms/upsertButtonText.ts +40 -0
  62. package/src/components/RichTextEditor/plugins/ButtonPlugin/transforms/wrapButton.ts +30 -0
  63. package/src/components/RichTextEditor/plugins/ButtonPlugin/types.ts +13 -0
  64. package/src/components/RichTextEditor/plugins/ButtonPlugin/utils/createButtonNode.ts +28 -0
  65. package/src/components/RichTextEditor/plugins/ButtonPlugin/utils/getButtonStyle.ts +14 -0
  66. package/src/components/RichTextEditor/plugins/ButtonPlugin/utils/getUrl.ts +18 -0
  67. package/src/components/RichTextEditor/plugins/ButtonPlugin/utils/index.ts +8 -0
  68. package/src/components/RichTextEditor/plugins/ButtonPlugin/utils/styles.ts +77 -0
  69. package/src/components/RichTextEditor/plugins/ButtonPlugin/utils/triggerFloatingButton.ts +23 -0
  70. package/src/components/RichTextEditor/plugins/ButtonPlugin/utils/triggerFloatingButtonEdit.ts +30 -0
  71. package/src/components/RichTextEditor/plugins/ButtonPlugin/utils/triggerFloatingButtonInsert.ts +45 -0
  72. package/src/components/RichTextEditor/plugins/ButtonPlugin/withButton.ts +106 -0
  73. package/src/components/RichTextEditor/plugins/LinkPlugin/FloatingLink/CustomFloatingLink.tsx +26 -0
  74. package/src/components/RichTextEditor/plugins/LinkPlugin/FloatingLink/EditLinkModal/EditModal.tsx +43 -0
  75. package/src/components/RichTextEditor/plugins/LinkPlugin/FloatingLink/EditLinkModal/index.ts +4 -0
  76. package/src/components/RichTextEditor/plugins/LinkPlugin/FloatingLink/EditLinkModal/useFloatingLinkEdit.ts +113 -0
  77. package/src/components/RichTextEditor/plugins/LinkPlugin/FloatingLink/FloatingLink.tsx +45 -0
  78. package/src/components/RichTextEditor/plugins/LinkPlugin/FloatingLink/InsertLinkModal/InsertLinkModal.tsx +5 -0
  79. package/src/components/RichTextEditor/plugins/LinkPlugin/FloatingLink/InsertLinkModal/InsertModal.tsx +105 -0
  80. package/src/components/RichTextEditor/plugins/LinkPlugin/FloatingLink/InsertLinkModal/index.ts +4 -0
  81. package/src/components/RichTextEditor/plugins/LinkPlugin/FloatingLink/InsertLinkModal/types.ts +16 -0
  82. package/src/components/RichTextEditor/plugins/LinkPlugin/FloatingLink/InsertLinkModal/useFloatingLinkInsert.ts +73 -0
  83. package/src/components/RichTextEditor/plugins/LinkPlugin/FloatingLink/InsertLinkModal/useInsertModal.ts +136 -0
  84. package/src/components/RichTextEditor/plugins/LinkPlugin/LinkButton.tsx +38 -0
  85. package/src/components/RichTextEditor/plugins/LinkPlugin/LinkMarkupElement/LinkMarkupElementNode.tsx +36 -0
  86. package/src/components/RichTextEditor/plugins/LinkPlugin/LinkMarkupElement/index.ts +11 -0
  87. package/src/components/RichTextEditor/plugins/LinkPlugin/id.ts +3 -0
  88. package/src/components/RichTextEditor/plugins/LinkPlugin/index.ts +48 -0
  89. package/src/components/RichTextEditor/plugins/LinkPlugin/types.ts +12 -0
  90. package/src/components/RichTextEditor/plugins/LinkPlugin/utils/getUrl.ts +30 -0
  91. package/src/components/RichTextEditor/plugins/LinkPlugin/utils/index.ts +4 -0
  92. package/src/components/RichTextEditor/plugins/LinkPlugin/utils/relativeUrlRegex.spec.ts +35 -0
  93. package/src/components/RichTextEditor/plugins/LinkPlugin/utils/relativeUrlRegex.ts +3 -0
  94. package/src/components/RichTextEditor/plugins/LinkPlugin/utils/url.spec.ts +75 -0
  95. package/src/components/RichTextEditor/plugins/LinkPlugin/utils/url.ts +21 -0
  96. package/src/components/RichTextEditor/plugins/TextStylePlugins/custom1Plugin.tsx +61 -0
  97. package/src/components/RichTextEditor/plugins/TextStylePlugins/custom2Plugin.tsx +61 -0
  98. package/src/components/RichTextEditor/plugins/TextStylePlugins/custom3Plugin.tsx +62 -0
  99. package/src/components/RichTextEditor/plugins/TextStylePlugins/heading1Plugin.tsx +61 -0
  100. package/src/components/RichTextEditor/plugins/TextStylePlugins/heading2Plugin.tsx +58 -0
  101. package/src/components/RichTextEditor/plugins/TextStylePlugins/heading3Plugin.tsx +58 -0
  102. package/src/components/RichTextEditor/plugins/TextStylePlugins/heading4Plugin.tsx +59 -0
  103. package/src/components/RichTextEditor/plugins/TextStylePlugins/helpers.tsx +44 -0
  104. package/src/components/RichTextEditor/plugins/TextStylePlugins/imageCaptionPlugin.tsx +61 -0
  105. package/src/components/RichTextEditor/plugins/TextStylePlugins/imageTitlePlugin.tsx +61 -0
  106. package/src/components/RichTextEditor/plugins/TextStylePlugins/index.ts +15 -0
  107. package/src/components/RichTextEditor/plugins/TextStylePlugins/paragraphPlugin.tsx +58 -0
  108. package/src/components/RichTextEditor/plugins/TextStylePlugins/quotePlugin.tsx +62 -0
  109. package/src/components/RichTextEditor/plugins/index.ts +6 -0
  110. package/src/components/RichTextEditor/plugins/shared/LinkSelector/DocumentLink.tsx +80 -0
  111. package/src/components/RichTextEditor/plugins/shared/LinkSelector/DocumentLinks.tsx +97 -0
  112. package/src/components/RichTextEditor/plugins/shared/LinkSelector/LinkSelector.spec.ct.tsx +138 -0
  113. package/src/components/RichTextEditor/plugins/shared/LinkSelector/LinkSelector.tsx +80 -0
  114. package/src/components/RichTextEditor/plugins/shared/LinkSelector/PageLink.tsx +83 -0
  115. package/src/components/RichTextEditor/plugins/shared/LinkSelector/PageLinks.tsx +68 -0
  116. package/src/components/RichTextEditor/plugins/shared/LinkSelector/SectionLink.tsx +37 -0
  117. package/src/components/RichTextEditor/plugins/shared/LinkSelector/index.ts +3 -0
  118. package/src/components/RichTextEditor/plugins/styles.ts +179 -0
  119. package/src/components/RichTextEditor/serializer/index.ts +3 -0
  120. package/src/components/RichTextEditor/serializer/nodes/button.ts +25 -0
  121. package/src/components/RichTextEditor/serializer/nodes/checkItemNode.ts +29 -0
  122. package/src/components/RichTextEditor/serializer/nodes/default.ts +52 -0
  123. package/src/components/RichTextEditor/serializer/nodes/link.ts +25 -0
  124. package/src/components/RichTextEditor/serializer/nodes/mentionHtmlNode.ts +17 -0
  125. package/src/components/RichTextEditor/serializer/serializeNodesToHtmlRecursive.ts +134 -0
  126. package/src/components/RichTextEditor/serializer/serializeToHtml.ts +49 -0
  127. package/src/components/RichTextEditor/serializer/utlis/reactCssPropsToCss.ts +21 -0
  128. package/src/components/RichTextEditor/serializer/utlis/serializeLeafToHtml.ts +32 -0
  129. package/src/components/RichTextEditor/types.ts +23 -0
  130. package/src/components/index.ts +7 -0
  131. package/src/helpers/addHttps.spec.ts +42 -0
  132. package/src/helpers/addHttps.ts +15 -0
  133. package/src/helpers/convertToRichTextValue.spec.ts +32 -0
  134. package/src/helpers/convertToRichTextValue.ts +6 -0
  135. package/src/helpers/customCoordinatesGetterFactory.spec.ts +69 -0
  136. package/src/helpers/customCoordinatesGetterFactory.ts +39 -0
  137. package/src/helpers/hasRichTextValue.spec.ts +63 -0
  138. package/src/helpers/hasRichTextValue.ts +29 -0
  139. package/src/helpers/index.ts +8 -0
  140. package/src/helpers/isDownloadable.spec.ts +47 -0
  141. package/src/helpers/isDownloadable.ts +7 -0
  142. package/src/helpers/mapColorPalettes.spec.ts +146 -0
  143. package/src/helpers/mapColorPalettes.ts +22 -0
  144. package/src/hooks/index.ts +4 -0
  145. package/src/hooks/useAttachments.spec.ts +79 -0
  146. package/src/hooks/useAttachments.ts +46 -0
  147. package/src/hooks/useDndSensors.spec.ts +40 -0
  148. package/src/hooks/useDndSensors.ts +23 -0
  149. package/src/index.ts +8 -0
  150. package/src/settings/background.spec.ts +173 -0
  151. package/src/settings/background.ts +49 -0
  152. package/src/settings/border.spec.ts +76 -0
  153. package/src/settings/border.ts +90 -0
  154. package/src/settings/borderRadius.spec.ts +30 -0
  155. package/src/settings/borderRadius.ts +73 -0
  156. package/src/settings/borderRadiusExtended.spec.ts +52 -0
  157. package/src/settings/borderRadiusExtended.ts +84 -0
  158. package/src/settings/defaultValues.ts +21 -0
  159. package/src/settings/gutter.spec.ts +60 -0
  160. package/src/settings/gutter.ts +75 -0
  161. package/src/settings/index.ts +14 -0
  162. package/src/settings/margin.spec.ts +42 -0
  163. package/src/settings/margin.ts +72 -0
  164. package/src/settings/marginExtended.spec.ts +45 -0
  165. package/src/settings/marginExtended.ts +91 -0
  166. package/src/settings/padding.spec.ts +42 -0
  167. package/src/settings/padding.ts +73 -0
  168. package/src/settings/paddingExtended.spec.ts +45 -0
  169. package/src/settings/paddingExtended.ts +91 -0
  170. package/src/settings/security.spec.ts +87 -0
  171. package/src/settings/security.ts +61 -0
  172. package/src/settings/securityDownloadable.spec.ts +46 -0
  173. package/src/settings/securityDownloadable.ts +33 -0
  174. package/src/settings/securityGlobalControl.ts +42 -0
  175. package/src/settings/types.ts +128 -0
  176. package/src/utilities/color/getReadableColor.spec.ts +32 -0
  177. package/src/utilities/color/getReadableColor.ts +34 -0
  178. package/src/utilities/color/index.ts +10 -0
  179. package/src/utilities/color/isDark.spec.ts +33 -0
  180. package/src/utilities/color/isDark.ts +29 -0
  181. package/src/utilities/color/setAlpha.spec.ts +28 -0
  182. package/src/utilities/color/setAlpha.ts +14 -0
  183. package/src/utilities/color/toColorObject.spec.ts +19 -0
  184. package/src/utilities/color/toColorObject.ts +16 -0
  185. package/src/utilities/color/toHex8String.spec.ts +17 -0
  186. package/src/utilities/color/toHex8String.ts +14 -0
  187. package/src/utilities/color/toHexString.spec.ts +17 -0
  188. package/src/utilities/color/toHexString.ts +10 -0
  189. package/src/utilities/color/toRgbaString.spec.ts +12 -0
  190. package/src/utilities/color/toRgbaString.ts +14 -0
  191. package/src/utilities/color/toShortRgba.spec.ts +16 -0
  192. package/src/utilities/color/toShortRgba.ts +35 -0
  193. package/src/utilities/index.ts +5 -0
  194. package/src/utilities/moveItemInArray.spec.ts +17 -0
  195. package/src/utilities/moveItemInArray.ts +21 -0
  196. package/src/utilities/react/getBackgroundColorStyles.spec.ts +18 -0
  197. package/src/utilities/react/getBackgroundColorStyles.ts +11 -0
  198. package/src/utilities/react/getBorderStyles.spec.ts +39 -0
  199. package/src/utilities/react/getBorderStyles.ts +21 -0
  200. package/src/utilities/react/getRadiusStyles.spec.ts +25 -0
  201. package/src/utilities/react/getRadiusStyles.ts +8 -0
  202. package/src/utilities/react/index.ts +6 -0
  203. package/src/utilities/react/joinClassNames.spec.ts +18 -0
  204. package/src/utilities/react/joinClassNames.ts +10 -0
  205. package/tailwind.config.js +27 -0
  206. package/tsconfig.json +3 -1
  207. package/vite.config.ts +11 -1
  208. package/dist/index.cjs.js +0 -2
  209. package/dist/index.cjs.js.map +0 -1
  210. package/dist/index.d.ts +0 -147
  211. package/dist/index.es.js +0 -9
  212. package/dist/index.es.js.map +0 -1
  213. package/dist/index.umd.js +0 -2
  214. package/dist/index.umd.js.map +0 -1
@@ -0,0 +1,87 @@
1
+ /* (c) Copyright Frontify Ltd., all rights reserved. */
2
+
3
+ import { describe, expect, it } from 'vitest';
4
+ import { getSecurityDownloadableSetting, getSecurityGlobalControlSetting } from './security';
5
+ import { Security } from './types';
6
+
7
+ describe('getSecurityGlobalControlSetting', () => {
8
+ it('should return global control setting without id', () => {
9
+ expect(getSecurityGlobalControlSetting()).toEqual({
10
+ id: 'security',
11
+ type: 'segmentedControls',
12
+ defaultValue: Security.Global,
13
+ helperText: 'Change global settings here.',
14
+ choices: [
15
+ {
16
+ value: Security.Global,
17
+ label: 'Global Settings',
18
+ },
19
+ {
20
+ value: Security.Custom,
21
+ label: 'Custom',
22
+ },
23
+ ],
24
+ });
25
+ });
26
+
27
+ it('should return global control setting with custom id', () => {
28
+ expect(getSecurityGlobalControlSetting('customId')).toEqual({
29
+ id: 'customId',
30
+ type: 'segmentedControls',
31
+ defaultValue: Security.Global,
32
+ helperText: 'Change global settings here.',
33
+ choices: [
34
+ {
35
+ value: Security.Global,
36
+ label: 'Global Settings',
37
+ },
38
+ {
39
+ value: Security.Custom,
40
+ label: 'Custom',
41
+ },
42
+ ],
43
+ });
44
+ });
45
+ });
46
+
47
+ describe('getSecurityDownloadableSetting', () => {
48
+ it('should return downloadable setting without arguments', () => {
49
+ expect(getSecurityDownloadableSetting()).toEqual({
50
+ id: 'downloadable',
51
+ type: 'switch',
52
+ defaultValue: false,
53
+ label: 'Downloadable',
54
+ show: expect.any(Function),
55
+ });
56
+ });
57
+
58
+ it('should return downloadable setting with custom id', () => {
59
+ expect(getSecurityDownloadableSetting({ id: 'customId' })).toEqual({
60
+ id: 'customId',
61
+ type: 'switch',
62
+ defaultValue: false,
63
+ label: 'Downloadable',
64
+ show: expect.any(Function),
65
+ });
66
+ });
67
+
68
+ it('should return downloadable setting with custom global control id', () => {
69
+ expect(getSecurityDownloadableSetting({ globalControlId: 'globalCustomId' })).toEqual({
70
+ id: 'downloadable',
71
+ type: 'switch',
72
+ defaultValue: false,
73
+ label: 'Downloadable',
74
+ show: expect.any(Function),
75
+ });
76
+ });
77
+
78
+ it('should return downloadable setting with custom id and global control id', () => {
79
+ expect(getSecurityDownloadableSetting({ id: 'customId', globalControlId: 'globalCustomId' })).toEqual({
80
+ id: 'customId',
81
+ type: 'switch',
82
+ defaultValue: false,
83
+ label: 'Downloadable',
84
+ show: expect.any(Function),
85
+ });
86
+ });
87
+ });
@@ -0,0 +1,61 @@
1
+ /* (c) Copyright Frontify Ltd., all rights reserved. */
2
+
3
+ import { SettingBlock } from '../';
4
+ import { Security } from './types';
5
+
6
+ /**
7
+ * Returns segment controls for global security settings.
8
+ *
9
+ * @param {string} id custom id for the setting block
10
+ *
11
+ * @returns {SettingBlock} Returns
12
+ */
13
+
14
+ export const getSecurityGlobalControlSetting = (id?: string): SettingBlock => {
15
+ const securityId = getSecurityGlobalControlId(id);
16
+ return {
17
+ id: securityId,
18
+ type: 'segmentedControls',
19
+ defaultValue: Security.Global,
20
+ helperText: 'Change global settings here.',
21
+ choices: [
22
+ {
23
+ value: Security.Global,
24
+ label: 'Global Settings',
25
+ },
26
+ {
27
+ value: Security.Custom,
28
+ label: 'Custom',
29
+ },
30
+ ],
31
+ };
32
+ };
33
+
34
+ /**
35
+ * Returns the downloadable security settings.
36
+ *
37
+ * @param {string} id custom id for the setting block
38
+ * @param {string} globalControlId custom id for the global control setting block
39
+ *
40
+ * @returns {SettingBlock} Returns downloadable security settings.
41
+ */
42
+
43
+ type SecurityDownloadableSettingType = {
44
+ id?: string;
45
+ globalControlId?: string;
46
+ };
47
+
48
+ export const getSecurityDownloadableSetting = (options?: SecurityDownloadableSettingType): SettingBlock => {
49
+ const securityId = getSecurityGlobalControlId(options?.globalControlId);
50
+ return {
51
+ id: options?.id ? options.id : 'downloadable',
52
+ type: 'switch',
53
+ defaultValue: false,
54
+ label: 'Downloadable',
55
+ show: (bundle) => bundle.getBlock(securityId)?.value === Security.Custom,
56
+ };
57
+ };
58
+
59
+ const getSecurityGlobalControlId = (id?: string): string => {
60
+ return id ? id : 'security';
61
+ };
@@ -0,0 +1,46 @@
1
+ /* (c) Copyright Frontify Ltd., all rights reserved. */
2
+
3
+ import { describe, expect, it } from 'vitest';
4
+ import { getSecurityDownloadableSetting } from './securityDownloadable';
5
+
6
+ describe('getSecurityDownloadableSetting', () => {
7
+ it('should return downloadable setting without arguments', () => {
8
+ expect(getSecurityDownloadableSetting()).toEqual({
9
+ id: 'downloadable',
10
+ type: 'switch',
11
+ defaultValue: false,
12
+ label: 'Downloadable',
13
+ show: expect.any(Function),
14
+ });
15
+ });
16
+
17
+ it('should return downloadable setting with custom id', () => {
18
+ expect(getSecurityDownloadableSetting({ id: 'customId' })).toEqual({
19
+ id: 'customId',
20
+ type: 'switch',
21
+ defaultValue: false,
22
+ label: 'Downloadable',
23
+ show: expect.any(Function),
24
+ });
25
+ });
26
+
27
+ it('should return downloadable setting with custom global control id', () => {
28
+ expect(getSecurityDownloadableSetting({ globalControlId: 'globalCustomId' })).toEqual({
29
+ id: 'downloadable',
30
+ type: 'switch',
31
+ defaultValue: false,
32
+ label: 'Downloadable',
33
+ show: expect.any(Function),
34
+ });
35
+ });
36
+
37
+ it('should return downloadable setting with custom id and global control id', () => {
38
+ expect(getSecurityDownloadableSetting({ id: 'customId', globalControlId: 'globalCustomId' })).toEqual({
39
+ id: 'customId',
40
+ type: 'switch',
41
+ defaultValue: false,
42
+ label: 'Downloadable',
43
+ show: expect.any(Function),
44
+ });
45
+ });
46
+ });
@@ -0,0 +1,33 @@
1
+ /* (c) Copyright Frontify Ltd., all rights reserved. */
2
+
3
+ import { SettingBlock } from '..';
4
+ import { Security } from './types';
5
+
6
+ /**
7
+ * Returns the downloadable security settings.
8
+ *
9
+ * @param {string} id custom id for the setting block
10
+ * @param {string} globalControlId custom id for the global control setting block
11
+ *
12
+ * @returns {SettingBlock} Returns downloadable security settings.
13
+ */
14
+
15
+ type SecurityDownloadableSettingType = {
16
+ id?: string;
17
+ globalControlId?: string;
18
+ };
19
+
20
+ export const getSecurityDownloadableSetting = (options?: SecurityDownloadableSettingType): SettingBlock => {
21
+ const securityId = getSecurityGlobalControlId(options?.globalControlId);
22
+ return {
23
+ id: options?.id ? options.id : 'downloadable',
24
+ type: 'switch',
25
+ defaultValue: false,
26
+ label: 'Downloadable',
27
+ show: (bundle) => bundle.getBlock(securityId)?.value === Security.Custom,
28
+ };
29
+ };
30
+
31
+ export const getSecurityGlobalControlId = (id?: string): string => {
32
+ return id || 'security';
33
+ };
@@ -0,0 +1,42 @@
1
+ /* (c) Copyright Frontify Ltd., all rights reserved. */
2
+
3
+ import { SettingBlock, createFooter } from '..';
4
+ import { Security } from './types';
5
+ import { getSecurityGlobalControlId } from './securityDownloadable';
6
+
7
+ /**
8
+ * Returns segment controls for global security settings.
9
+ *
10
+ * @param {string} id custom id for the setting block
11
+ *
12
+ * @returns {SettingBlock} Returns
13
+ */
14
+
15
+ export const getSecurityGlobalControlSetting = (id?: string): SettingBlock[] => {
16
+ const securityId = getSecurityGlobalControlId(id);
17
+ return [
18
+ {
19
+ id: securityId,
20
+ type: 'segmentedControls',
21
+ defaultValue: Security.Global,
22
+ choices: [
23
+ {
24
+ value: Security.Global,
25
+ label: 'Global Settings',
26
+ },
27
+ {
28
+ value: Security.Custom,
29
+ label: 'Custom',
30
+ },
31
+ ],
32
+ },
33
+ {
34
+ id: 'globalSettingsInfo',
35
+ type: 'notification',
36
+ footer: createFooter({
37
+ label: 'Change global settings [here].',
38
+ replace: { here: { event: 'general-settings.open' } },
39
+ }),
40
+ },
41
+ ];
42
+ };
@@ -0,0 +1,128 @@
1
+ /* (c) Copyright Frontify Ltd., all rights reserved. */
2
+
3
+ import { Color } from '@frontify/sidebar-settings';
4
+
5
+ export enum BorderStyle {
6
+ Solid = 'Solid',
7
+ Dashed = 'Dashed',
8
+ Dotted = 'Dotted',
9
+ }
10
+
11
+ export const borderStyleMap: Record<BorderStyle, string> = {
12
+ [BorderStyle.Solid]: 'solid',
13
+ [BorderStyle.Dotted]: 'dotted',
14
+ [BorderStyle.Dashed]: 'dashed',
15
+ };
16
+
17
+ export enum Radius {
18
+ None = 'None',
19
+ Small = 'Small',
20
+ Medium = 'Medium',
21
+ Large = 'Large',
22
+ }
23
+
24
+ export const radiusStyleMap: Record<Radius, string> = {
25
+ [Radius.None]: '0px',
26
+ [Radius.Small]: '2px',
27
+ [Radius.Medium]: '4px',
28
+ [Radius.Large]: '12px',
29
+ };
30
+
31
+ export enum Padding {
32
+ None = 'None',
33
+ Small = 'Small',
34
+ Medium = 'Medium',
35
+ Large = 'Large',
36
+ }
37
+
38
+ export const paddingStyleMap: Record<Padding, string> = {
39
+ [Padding.None]: '0px',
40
+ [Padding.Small]: '24px',
41
+ [Padding.Medium]: '36px',
42
+ [Padding.Large]: '60px',
43
+ };
44
+
45
+ export type PaddingSettings = {
46
+ paddingChoice: Padding;
47
+ hasCustomPaddingValue: boolean;
48
+ paddingValue: string;
49
+ };
50
+
51
+ export type PaddingExtendedSettings = {
52
+ hasExtendedCustomPadding: boolean;
53
+ extendedPaddingChoice: Padding;
54
+ extendedPaddingTop: string;
55
+ extendedPaddingRight: string;
56
+ extendedPaddingBottom: string;
57
+ extendedPaddingLeft: string;
58
+ };
59
+
60
+ export type RadiusExtendedSettings = {
61
+ hasExtendedCustomRadius: boolean;
62
+ extendedRadiusChoice: Radius;
63
+ extendedRadiusTopLeft: string;
64
+ extendedRadiusTopRight: string;
65
+ extendedRadiusBottomLeft: string;
66
+ extendedRadiusBottomRight: string;
67
+ };
68
+
69
+ export type BorderSettings = {
70
+ hasBorder: boolean;
71
+ borderStyle: BorderStyle;
72
+ borderWidth: string;
73
+ borderColor: Color;
74
+ };
75
+
76
+ export type RadiusSettings = {
77
+ hasRadius: boolean;
78
+ radiusValue: string;
79
+ radiusChoice: Radius;
80
+ };
81
+
82
+ export enum Margin {
83
+ None = 'None',
84
+ Small = 'Small',
85
+ Medium = 'Medium',
86
+ Large = 'Large',
87
+ }
88
+
89
+ export const marginStyleMap: Record<Margin, string> = {
90
+ [Margin.None]: '0px',
91
+ [Margin.Small]: '24px',
92
+ [Margin.Medium]: '36px',
93
+ [Margin.Large]: '60px',
94
+ };
95
+
96
+ export type MarginSettings = {
97
+ marginChoice: Margin;
98
+ hasCustomMarginValue: boolean;
99
+ marginValue: string;
100
+ };
101
+
102
+ export type MarginExtendedSettings = {
103
+ hasExtendedCustomMargin: boolean;
104
+ extendedMarginChoice: Margin;
105
+ extendedMarginTop: string;
106
+ extendedMarginRight: string;
107
+ extendedMarginBottom: string;
108
+ extendedMarginLeft: string;
109
+ };
110
+
111
+ export enum Security {
112
+ Global = 'Global',
113
+ Custom = 'Custom',
114
+ }
115
+
116
+ export enum GutterSpacing {
117
+ Auto = 'Auto',
118
+ S = 'S',
119
+ M = 'M',
120
+ L = 'L',
121
+ }
122
+
123
+ export const gutterSpacingStyleMap: Record<GutterSpacing, string> = {
124
+ [GutterSpacing.Auto]: '4px',
125
+ [GutterSpacing.S]: '10px',
126
+ [GutterSpacing.M]: '30px',
127
+ [GutterSpacing.L]: '50px',
128
+ };
@@ -0,0 +1,32 @@
1
+ /* (c) Copyright Frontify Ltd., all rights reserved. */
2
+
3
+ import { readability } from '@ctrl/tinycolor';
4
+ import { describe, expect, test } from 'vitest';
5
+ import { getReadableColor } from './getReadableColor';
6
+
7
+ describe('getReadableColor', () => {
8
+ const data = [
9
+ {
10
+ textColor: { r: 255, g: 255, b: 255 },
11
+ backgroundColor: { r: 0, g: 0, b: 0 },
12
+ },
13
+ {
14
+ textColor: { r: 255, g: 255, b: 255 },
15
+ backgroundColor: { r: 255, g: 255, b: 255 },
16
+ },
17
+ {
18
+ textColor: { r: 230, g: 230, b: 0 },
19
+ backgroundColor: { r: 229, g: 229, b: 10 },
20
+ },
21
+ {
22
+ textColor: { r: 120, g: 120, b: 120 },
23
+ backgroundColor: { r: 120, g: 120, b: 120, a: 0.1 },
24
+ },
25
+ ];
26
+
27
+ test.each(data)('validates against expected values', ({ textColor, backgroundColor }) => {
28
+ const result = getReadableColor(textColor, backgroundColor);
29
+ const colorReadability = readability(result, backgroundColor);
30
+ expect(colorReadability).toBeGreaterThan(4.5);
31
+ });
32
+ });
@@ -0,0 +1,34 @@
1
+ /* (c) Copyright Frontify Ltd., all rights reserved. */
2
+
3
+ import tinycolor, { ColorInput, readability } from '@ctrl/tinycolor';
4
+ import { toShortRgba } from './toShortRgba';
5
+ import { Color } from '@frontify/sidebar-settings';
6
+
7
+ /**
8
+ * Returns darkened text color for a given background color, so that it is readable and has enough contrast (above 4.5)
9
+ *
10
+ * @param {Object} textColor Object of RGBA values
11
+ * @param {Object} backgroundColor Object of RGBA values
12
+ * @returns {string} To be used as css value
13
+ */
14
+
15
+ const isRgbaLongFormat = (value: unknown): value is Color => {
16
+ const requiredKeys = ['red', 'green', 'blue'];
17
+ return typeof value === 'object' && requiredKeys.every((i) => value?.hasOwnProperty(i));
18
+ };
19
+
20
+ export const getReadableColor = (textColor: unknown, backgroundColor: unknown): string => {
21
+ const inputTextColor = isRgbaLongFormat(textColor) ? toShortRgba(textColor) : (textColor as ColorInput);
22
+ const inputBackgroundColor = isRgbaLongFormat(backgroundColor)
23
+ ? toShortRgba(backgroundColor)
24
+ : (backgroundColor as ColorInput);
25
+ let parsedTextColor = tinycolor(inputTextColor);
26
+ const parsedBackgroundColor = tinycolor(inputBackgroundColor);
27
+
28
+ //darken the text color until readability is good
29
+ while (readability(parsedTextColor, parsedBackgroundColor) < 4.5) {
30
+ parsedTextColor = parsedTextColor.darken(1);
31
+ }
32
+
33
+ return parsedTextColor.toRgbString();
34
+ };
@@ -0,0 +1,10 @@
1
+ /* (c) Copyright Frontify Ltd., all rights reserved. */
2
+
3
+ export * from './isDark';
4
+ export * from './toHex8String';
5
+ export * from './toHexString';
6
+ export * from './toRgbaString';
7
+ export * from './setAlpha';
8
+ export * from './toColorObject';
9
+ export * from './getReadableColor';
10
+ export * from './toShortRgba';
@@ -0,0 +1,33 @@
1
+ /* (c) Copyright Frontify Ltd., all rights reserved. */
2
+
3
+ import { isDark } from './isDark';
4
+ import { describe, expect, test } from 'vitest';
5
+
6
+ describe('isDark', () => {
7
+ const data = [
8
+ { color: { red: 0, green: 0, blue: 0 }, expected: true },
9
+ { color: { red: 255, green: 255, blue: 255 }, expected: false },
10
+ { color: { red: 130, green: 95, blue: 255 }, expected: true },
11
+ { color: '#000000', expected: true },
12
+ { color: '#FFFFFF', expected: false },
13
+ { color: 'rgb(0,0,0)', expected: true },
14
+ { color: 'rgb(255,255,255)', expected: false },
15
+ ];
16
+
17
+ test.each(data)('validate values correctly', ({ color, expected }) => {
18
+ expect(isDark(color)).toBe(expected);
19
+ });
20
+ });
21
+
22
+ describe('isDark with custom threshold', () => {
23
+ const data = [
24
+ { color: { red: 0, green: 0, blue: 0 }, threshold: 150, expected: true },
25
+ { color: { red: 255, green: 102, blue: 0 }, threshold: 150, expected: true },
26
+ { color: { red: 255, green: 147, blue: 73 }, threshold: 171, expected: true },
27
+ { color: { red: 255, green: 255, blue: 255 }, threshold: 150, expected: false },
28
+ ];
29
+
30
+ test.each(data)('validate values correctly', ({ color, threshold, expected }) => {
31
+ expect(isDark(color, threshold)).toBe(expected);
32
+ });
33
+ });
@@ -0,0 +1,29 @@
1
+ /* (c) Copyright Frontify Ltd., all rights reserved. */
2
+
3
+ import tinycolor, { ColorInput } from '@ctrl/tinycolor';
4
+ import { toShortRgba } from './toShortRgba';
5
+ import { Color } from '@frontify/sidebar-settings';
6
+
7
+ /**
8
+ * Calculates if text should be in a light color depending on color (e.g. background-color)
9
+ *
10
+ * @param {Object} value Object of RGBA values
11
+ * @param {Number|undefined} threshold Threshold for the brightness
12
+ * @returns {Boolean} Return if the color is dark
13
+ */
14
+
15
+ const isRgbaLongFormat = (value: unknown): value is Color => {
16
+ const requiredKeys = ['red', 'green', 'blue'];
17
+ return typeof value === 'object' && requiredKeys.every((i) => value?.hasOwnProperty(i));
18
+ };
19
+
20
+ export const isDark = (color: unknown, threshold?: number): boolean => {
21
+ const inputColor = isRgbaLongFormat(color) ? toShortRgba(color) : (color as ColorInput);
22
+ const parsedColor = tinycolor(inputColor);
23
+
24
+ if (threshold) {
25
+ return parsedColor.getBrightness() < threshold;
26
+ }
27
+
28
+ return parsedColor.isDark() || (parsedColor.getAlpha() > 0.25 && parsedColor.getAlpha() < 1);
29
+ };
@@ -0,0 +1,28 @@
1
+ /* (c) Copyright Frontify Ltd., all rights reserved. */
2
+
3
+ import { setAlpha } from './setAlpha';
4
+ import { describe, expect, test } from 'vitest';
5
+
6
+ describe('setAlpha', () => {
7
+ const data = [
8
+ {
9
+ color: 'rgba(255, 255, 255, 0.1)',
10
+ alpha: 1,
11
+ expected: 'rgb(255, 255, 255)',
12
+ },
13
+ {
14
+ color: 'rgb(255, 255, 255)',
15
+ alpha: 0.9,
16
+ expected: 'rgba(255, 255, 255, 0.9)',
17
+ },
18
+ {
19
+ color: '#00000',
20
+ alpha: 0.9,
21
+ expected: 'rgba(0, 0, 0, 0.9)',
22
+ },
23
+ ];
24
+
25
+ test.each(data)('validates against expected values', ({ color, alpha, expected }) => {
26
+ expect(setAlpha(alpha, color)).toBe(expected);
27
+ });
28
+ });
@@ -0,0 +1,14 @@
1
+ /* (c) Copyright Frontify Ltd., all rights reserved. */
2
+
3
+ import tinycolor from '@ctrl/tinycolor';
4
+
5
+ /**
6
+ * Sets alpha value and returns rgba string.
7
+ *
8
+ * @param {string} color Rgb or hex string.
9
+ * @returns {String} To be used as css value.
10
+ */
11
+
12
+ export const setAlpha = (alpha: number, color?: string): string => {
13
+ return tinycolor(color).setAlpha(alpha).toRgbString();
14
+ };
@@ -0,0 +1,19 @@
1
+ /* (c) Copyright Frontify Ltd., all rights reserved. */
2
+
3
+ import { describe, expect, test } from 'vitest';
4
+ import { toColorObject } from './toColorObject';
5
+
6
+ describe('toColorObject', () => {
7
+ const data = [
8
+ { expected: { red: 255, green: 255, blue: 255, alpha: 1 }, color: '#ffffffff' },
9
+ { expected: { red: 255, green: 221, blue: 255, alpha: 1 }, color: '#ffddffff' },
10
+ { expected: { red: 255, green: 255, blue: 15, alpha: 0 }, color: '#ffff0f00' },
11
+ { expected: { red: 238, green: 35, blue: 84, alpha: 0.4 }, color: '#ee235466' },
12
+ { expected: { red: 255, green: 0, blue: 0, alpha: 1 }, color: 'rgb(255,0,0)' },
13
+ { expected: { red: 255, green: 0, blue: 0, alpha: 0.5 }, color: 'rgba(255,0,0,0.5)' },
14
+ ];
15
+
16
+ test.each(data)('validates against expected values', ({ color, expected }) => {
17
+ expect(toColorObject(color)).toEqual(expected);
18
+ });
19
+ });
@@ -0,0 +1,16 @@
1
+ /* (c) Copyright Frontify Ltd., all rights reserved. */
2
+
3
+ import { Color } from '@frontify/fondue';
4
+ import tinycolor from '@ctrl/tinycolor';
5
+
6
+ /**
7
+ * Maps color strings to color objects.
8
+ *
9
+ * @param {String} String representing color
10
+ * @returns {Color} Color object
11
+ */
12
+
13
+ export const toColorObject = (colorString: string): Color => {
14
+ const { r, g, b, a } = tinycolor(colorString);
15
+ return { red: r, green: g, blue: b, alpha: a };
16
+ };
@@ -0,0 +1,17 @@
1
+ /* (c) Copyright Frontify Ltd., all rights reserved. */
2
+
3
+ import { toHex8String } from './toHex8String';
4
+ import { describe, expect, test } from 'vitest';
5
+
6
+ describe('toHex8String', () => {
7
+ const data = [
8
+ { color: { red: 255, green: 255, blue: 255 }, expected: '#ffffffff' },
9
+ { color: { red: 255, green: 221, blue: 255, alpha: 1 }, expected: '#ffddffff' },
10
+ { color: { red: 255, green: 255, blue: 15, alpha: 0 }, expected: '#ffff0f00' },
11
+ { color: { red: 238, green: 35, blue: 84, alpha: 0.4 }, expected: '#ee235466' },
12
+ ];
13
+
14
+ test.each(data)('validates against expected values', ({ color, expected }) => {
15
+ expect(toHex8String(color)).toBe(expected);
16
+ });
17
+ });
@@ -0,0 +1,14 @@
1
+ /* (c) Copyright Frontify Ltd., all rights reserved. */
2
+
3
+ import { Color } from '@frontify/fondue';
4
+ import tinycolor from '@ctrl/tinycolor';
5
+ import { toShortRgba } from './toShortRgba';
6
+
7
+ /**
8
+ * Maps color object of rgba values to hex alpha string.
9
+ *
10
+ * @param {Object} Color object
11
+ * @returns {String} To be used as css value.
12
+ */
13
+
14
+ export const toHex8String = (color: Color): string => tinycolor(toShortRgba(color)).toHex8String();
@@ -0,0 +1,17 @@
1
+ /* (c) Copyright Frontify Ltd., all rights reserved. */
2
+
3
+ import { toHexString } from './toHexString';
4
+ import { describe, expect, test } from 'vitest';
5
+
6
+ describe('toHexString', () => {
7
+ const data = [
8
+ { color: { red: 255, green: 255, blue: 255 }, expected: '#ffffff' },
9
+ { color: { red: 255, green: 221, blue: 255 }, expected: '#ffddff' },
10
+ { color: { red: 255, green: 255, blue: 15 }, expected: '#ffff0f' },
11
+ { color: { red: 238, green: 35, blue: 84 }, expected: '#ee2354' },
12
+ ];
13
+
14
+ test.each(data)('validates against expected values', ({ color, expected }) => {
15
+ expect(toHexString(color)).toBe(expected);
16
+ });
17
+ });