@eeacms/volto-tabs-block 6.0.2 → 7.0.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 (41) hide show
  1. package/CHANGELOG.md +84 -21
  2. package/README.md +18 -1
  3. package/locales/de/LC_MESSAGES/volto.po +76 -29
  4. package/locales/en/LC_MESSAGES/volto.po +76 -29
  5. package/locales/es/LC_MESSAGES/volto.po +77 -30
  6. package/locales/it/LC_MESSAGES/volto.po +76 -29
  7. package/locales/pt_BR/LC_MESSAGES/volto.po +77 -30
  8. package/locales/ro/LC_MESSAGES/volto.po +76 -29
  9. package/locales/volto.pot +77 -30
  10. package/package.json +1 -1
  11. package/src/components/Edit.jsx +119 -102
  12. package/src/components/View.jsx +6 -4
  13. package/src/components/index.js +1 -0
  14. package/src/components/layoutSchema.js +3 -1
  15. package/src/components/schema.js +169 -70
  16. package/src/components/templates/accordion/Edit.jsx +28 -199
  17. package/src/components/templates/accordion/View.jsx +42 -64
  18. package/src/components/templates/accordion/index.js +1 -2
  19. package/src/components/templates/accordion/schema.js +33 -40
  20. package/src/components/templates/carousel/HorizontalView.jsx +3 -0
  21. package/src/components/templates/carousel/VerticalView.jsx +3 -0
  22. package/src/components/templates/carousel/index.js +1 -2
  23. package/src/components/templates/carousel/schema.js +19 -25
  24. package/src/components/templates/default/Edit.jsx +90 -50
  25. package/src/components/templates/default/View.jsx +112 -43
  26. package/src/components/templates/default/index.js +2 -2
  27. package/src/components/templates/default/schema.js +69 -77
  28. package/src/components/templates/horizontal-responsive/Edit.jsx +63 -46
  29. package/src/components/templates/horizontal-responsive/View.jsx +33 -37
  30. package/src/components/templates/horizontal-responsive/index.js +1 -6
  31. package/src/components/templates/horizontal-responsive/schema.js +6 -5
  32. package/src/helpers.js +14 -10
  33. package/src/helpers.test.js +14 -8
  34. package/src/index.js +34 -22
  35. package/src/less/carousel.less +9 -0
  36. package/src/less/edit.less +26 -0
  37. package/src/less/menu.less +118 -4
  38. package/src/less/menu.variables +16 -0
  39. package/src/less/tabs.less +53 -23
  40. package/src/less/tabs.variables +3 -0
  41. package/src/widgets/TabsWidget.jsx +158 -68
@@ -4,22 +4,28 @@ import {
4
4
  scrollToTarget,
5
5
  getParentTabFromHash,
6
6
  } from './helpers';
7
- import { emptyBlocksForm } from '@plone/volto/helpers';
7
+ // import { emptyBlocksForm } from '@plone/volto/helpers';
8
8
  import { visitBlocks, toSlug } from '@eeacms/volto-anchors/helpers';
9
9
 
10
- jest.mock('@plone/volto/helpers', () => ({
11
- emptyBlocksForm: jest.fn(),
12
- }));
10
+ // jest.mock('@plone/volto/helpers', () => ({
11
+ // emptyBlocksForm: jest.fn(),
12
+ // }));
13
13
 
14
14
  jest.mock('@eeacms/volto-anchors/helpers', () => ({
15
15
  visitBlocks: jest.fn(),
16
16
  toSlug: jest.fn(),
17
17
  }));
18
18
 
19
+ const schema = {
20
+ fieldsets: [{ id: 'default', fields: [] }],
21
+ properties: {},
22
+ required: [],
23
+ };
24
+
19
25
  describe('empty function', () => {
20
26
  it('returns a tab block with unique ID', () => {
21
- emptyBlocksForm.mockReturnValue({});
22
- const result = empty();
27
+ // emptyBlocksForm.mockReturnValue({});
28
+ const result = empty({ schema });
23
29
  expect(Object.keys(result.blocks)).toHaveLength(1);
24
30
  expect(result.blocks[Object.keys(result.blocks)[0]]['@type']).toEqual(
25
31
  'tab',
@@ -30,8 +36,8 @@ describe('empty function', () => {
30
36
 
31
37
  describe('emptyTab function', () => {
32
38
  it('returns a tab block', () => {
33
- emptyBlocksForm.mockReturnValue({});
34
- const result = emptyTab();
39
+ // emptyBlocksForm.mockReturnValue({});
40
+ const result = emptyTab({ schema });
35
41
  expect(result['@type']).toEqual('tab');
36
42
  });
37
43
  });
package/src/index.js CHANGED
@@ -9,13 +9,10 @@ import {
9
9
  HorizontalResponsiveView,
10
10
  HorizontalCarouselView,
11
11
  VerticalCarouselView,
12
- defaultSchema,
13
- accordionSchema,
14
- horizontalResponsiveSchema,
15
- carouselSchema,
16
12
  layoutSchema,
17
13
  TabsEdit,
18
14
  TabsView,
15
+ blockSchema,
19
16
  } from '@eeacms/volto-tabs-block/components';
20
17
  import { TABS_BLOCK } from './constants';
21
18
  import { TabsWidget } from './widgets';
@@ -33,9 +30,21 @@ defineMessages({
33
30
  id: 'Accordion responsive',
34
31
  defaultMessage: 'Accordion responsive',
35
32
  },
33
+ carouselHorizontal: {
34
+ defaultMessage: 'Carousel horizontal',
35
+ id: 'Carousel horizontal',
36
+ },
37
+ carouselVerticalPrototype: {
38
+ defaultMessage: 'Carousel vertical (prototype)',
39
+ id: 'Carousel vertical (prototype)',
40
+ },
41
+ horizontalResponsive: {
42
+ defaultMessage: 'Horizontal responsive',
43
+ id: 'Horizontal responsive',
44
+ },
36
45
  });
37
46
 
38
- export default (config) => {
47
+ const applyConfig = (config) => {
39
48
  config.blocks.blocksConfig[TABS_BLOCK] = {
40
49
  id: TABS_BLOCK,
41
50
  title: 'Tabs',
@@ -51,21 +60,23 @@ export default (config) => {
51
60
  view: [],
52
61
  },
53
62
  blockHasOwnFocusManagement: true,
63
+ blockSchema: blockSchema,
54
64
  schema: layoutSchema(config),
55
- templates: {
56
- default: {
65
+ variations: [
66
+ {
57
67
  id: 'default',
58
68
  title: 'Default',
69
+ isDefault: true,
59
70
  edit: DefaultEdit,
60
71
  view: DefaultView,
61
- schema: defaultSchema,
72
+ schemaEnhancer: DefaultEdit.schemaEnhancer,
62
73
  },
63
- accordion: {
64
- id: 'accordionResponsive',
74
+ {
75
+ id: 'accordion',
65
76
  title: 'Accordion responsive',
66
77
  edit: AccordionEdit,
67
78
  view: AccordionView,
68
- schema: accordionSchema,
79
+ schemaEnhancer: AccordionEdit.schemaEnhancer,
69
80
  transformWidth: 800,
70
81
  icons: {
71
82
  closed: rightSVG,
@@ -73,29 +84,28 @@ export default (config) => {
73
84
  size: '24px',
74
85
  },
75
86
  },
76
- 'horizontal-responsive': {
77
- id: 'horizontalResponsive',
87
+ {
88
+ id: 'horizontal-responsive',
78
89
  title: 'Horizontal responsive',
79
90
  edit: HorizontalResponsiveEdit,
80
91
  view: HorizontalResponsiveView,
81
- schema: horizontalResponsiveSchema,
92
+ schemaEnhancer: HorizontalResponsiveEdit.schemaEnhancer,
82
93
  },
83
- carousel: {
84
- id: 'carouselHorizontal',
94
+ {
95
+ id: 'carousel-horizontal',
85
96
  title: 'Carousel horizontal',
86
97
  edit: DefaultEdit,
87
98
  view: HorizontalCarouselView,
88
- schema: carouselSchema,
99
+ schemaEnhancer: HorizontalCarouselView.schemaEnhancer,
89
100
  },
90
- carousel_vertical: {
91
- id: 'carouselVerticalPrototype',
101
+ {
102
+ id: 'carousel-vertical',
92
103
  title: 'Carousel vertical (prototype)',
93
104
  edit: DefaultEdit,
94
105
  view: VerticalCarouselView,
95
- schema: carouselSchema,
106
+ schemaEnhancer: VerticalCarouselView.schemaEnhancer,
96
107
  },
97
- ...(config.blocks.blocksConfig[TABS_BLOCK]?.templates || {}),
98
- },
108
+ ],
99
109
  getBlocks: (data) => {
100
110
  const { blocks = {}, blocks_layout = {} } = data?.data;
101
111
  if (blocks_layout?.items?.length) {
@@ -116,3 +126,5 @@ export default (config) => {
116
126
 
117
127
  return config;
118
128
  };
129
+
130
+ export default applyConfig;
@@ -7,6 +7,15 @@
7
7
  .loadAddonVariables();
8
8
 
9
9
  .tabs-block {
10
+ // ensure only active slide is selectable
11
+ .slick-slide {
12
+ visibility: hidden;
13
+ }
14
+
15
+ .slick-active {
16
+ visibility: visible;
17
+ }
18
+
10
19
  .slick-slider {
11
20
  z-index: 2;
12
21
  display: flex !important;
@@ -138,3 +138,29 @@
138
138
  }
139
139
  }
140
140
  }
141
+
142
+ .block-editor-tabs_block {
143
+ .block.tabs_block.selected::before,
144
+ .block.tabs_block:hover::before {
145
+ border-style: dashed;
146
+ }
147
+
148
+ fieldset {
149
+ border: none;
150
+
151
+ legend {
152
+ position: absolute;
153
+ z-index: 3;
154
+ top: -1.3em;
155
+ left: 0;
156
+ width: fit-content;
157
+ padding: 0 1rem;
158
+ margin-right: auto;
159
+ margin-left: auto;
160
+ background-color: @pageBackground;
161
+ color: @borderColor;
162
+ cursor: pointer;
163
+ text-align: center;
164
+ }
165
+ }
166
+ }
@@ -17,6 +17,18 @@
17
17
  overflow-y: hidden;
18
18
  }
19
19
 
20
+ .ui.secondary.inverted.pointing.menu {
21
+ border-width: 0 0 4px 0;
22
+ }
23
+
24
+ .ui.secondary.inverted.menu .active.item:not(.remove-margin) {
25
+ background-color: @menuItemInvertedActiveBackgroundColor !important;
26
+ }
27
+
28
+ .ui.menu .addition-button .menu-item-text {
29
+ line-height: 1;
30
+ }
31
+
20
32
  .remove-menu :not(.RRT__tab--collapsed) {
21
33
  padding-top: 0 !important;
22
34
  padding-left: 0 !important;
@@ -27,6 +39,112 @@
27
39
  margin-bottom: @menuMarginButton;
28
40
  }
29
41
 
42
+ .ui.item {
43
+ cursor: pointer;
44
+ }
45
+
46
+ .ui.menu:not(.inverted, .pointing) .active.item:not(.remove-margin) {
47
+ background-color: @menuItemActiveBackgroundColor;
48
+ }
49
+
50
+ .RRT__tabs.tabs-accessibility.ui.inverted.menu {
51
+ background-color: @menuItemInvertedBackgroundColor;
52
+
53
+ .item {
54
+ color: @menuItemInvertedTextColor !important;
55
+ }
56
+
57
+ .item.active {
58
+ border-color: @secondaryPointingInvertedActiveBorderColor;
59
+ color: @menuItemInvertedActiveTextColor !important;
60
+ }
61
+
62
+ .item:hover {
63
+ color: @menuItemInvertedHoverTextColor !important;
64
+ }
65
+ }
66
+
67
+ .tab-icon {
68
+ display: block !important;
69
+ }
70
+
71
+ .asset-position {
72
+ .image {
73
+ &.icon {
74
+ width: @tabImageSmallSize;
75
+ }
76
+
77
+ &.tile {
78
+ width: @tabImageMediumSize;
79
+ }
80
+
81
+ &.thumb {
82
+ width: @tabImageLargeSize;
83
+ }
84
+ }
85
+
86
+ .icon {
87
+ &.small {
88
+ font-size: @tabIconSmallSize;
89
+ }
90
+
91
+ &.medium {
92
+ font-size: @tabIconMediumSize;
93
+ }
94
+
95
+ &.large {
96
+ font-size: @tabIconLargeSize;
97
+ }
98
+ }
99
+ }
100
+
101
+ .RRT__accordion .tab-with-icon {
102
+ flex-direction: row-reverse;
103
+ gap: 0.25rem;
104
+
105
+ .icon {
106
+ font-size: 1.25rem;
107
+ --accordion-title-icon-order: 0;
108
+ }
109
+ }
110
+
111
+ .accordion-title {
112
+ display: flex;
113
+ }
114
+
115
+ .asset-top,
116
+ .asset-left,
117
+ .asset-right {
118
+ display: flex;
119
+ align-items: center;
120
+ gap: 0.6em;
121
+
122
+ .menu-item-text {
123
+ margin: 0;
124
+ }
125
+ }
126
+
127
+ .asset-top {
128
+ flex-direction: column;
129
+ text-align: center;
130
+
131
+ .icon {
132
+ display: block !important;
133
+ }
134
+ }
135
+
136
+ .asset-left {
137
+ flex-direction: row;
138
+ }
139
+
140
+ .asset-right {
141
+ flex-direction: row-reverse;
142
+ }
143
+
144
+ .menu-item-count {
145
+ display: @menuItemCountDisplay;
146
+ }
147
+
30
148
  > .styled > .tabs > .ui.menu,
31
149
  > .styled > .tabs > .ui.grid > .column > .ui.menu,
32
150
  > .tabs > .ui.menu,
@@ -88,10 +206,6 @@
88
206
  }
89
207
  }
90
208
 
91
- .menu-item-count {
92
- display: @menuItemCountDisplay;
93
- }
94
-
95
209
  &.active {
96
210
  border-width: 0.2rem;
97
211
  }
@@ -11,11 +11,27 @@
11
11
  @menuTitleHoverColor: #013C60;
12
12
  @menuTitleHoverBackground: none;
13
13
 
14
+ /* Tab Icons */
15
+ @tabImageSmallSize: 48px;
16
+ @tabImageMediumSize: 64px;
17
+ @tabImageLargeSize: 80px;
18
+ @tabIconSmallSize: 48px;
19
+ @tabIconMediumSize: 64px;
20
+ @tabIconLargeSize: 80px;
21
+
14
22
  /* Menu description */
15
23
  @menuDescriptionColor: #636363;
16
24
 
17
25
  /* Menu item */
18
26
  @menuItemCountDisplay: none;
27
+ @secondaryPointingInvertedActiveBorderColor: var(--inverted-secondary-active-border-color, @pink);
28
+ @menuItemActiveBackgroundColor: var(--tab-active-bg-color, rgba(0, 0, 0, 0.05));
29
+ @menuItemInvertedBackgroundColor: var(--tab-inverted-bg-color, #C7D5D8);
30
+ @menuItemInvertedActiveBackgroundColor: var(--tab-inverted-active-bg-color, rgba(0, 0, 0, 0.1));
31
+ @menuItemInvertedActiveTextColor: var(--tab-inverted-active-text-color, @textColor);
32
+ @menuItemInvertedTextColor: var(--tab-inverted-text-color, @textColor);
33
+ @menuItemInvertedHoverTextColor:var(--tab-inverted-hover-text-color, @textColor);
34
+
19
35
 
20
36
  @accordionMenuItemBackground: #F3F4F5; /* not used */
21
37
  @accordionTabBackground: transparent;
@@ -6,36 +6,48 @@
6
6
 
7
7
  .loadAddonVariables();
8
8
 
9
- .tabs-block {
10
- .remove-menu.active {
11
- overflow: revert; /* needed for edit double click to modify title to remove scrollbar */
9
+ @keyframes slide-down {
10
+ 0% {
11
+ overflow: hidden;
12
+ max-height: 0;
13
+ opacity: 0;
14
+ visibility: hidden;
12
15
  }
13
16
 
14
- .tabs-accessibility {
15
- .ui.button.item:focus-visible {
16
- outline: 1px dotted #212121 !important;
17
- outline: 5px auto -webkit-focus-ring-color !important;
18
- }
17
+ 95% {
18
+ overflow: hidden;
19
+ max-height: @animationContentMaxHeight;
20
+ visibility: visible;
21
+ }
19
22
 
20
- a:focus-visible {
21
- outline: 1px dotted #212121 !important;
22
- outline: 5px auto -webkit-focus-ring-color !important;
23
- }
23
+ 100% {
24
+ max-height: auto;
25
+ opacity: 1;
26
+ visibility: visible;
27
+ }
28
+ }
24
29
 
25
- .slick-current:focus-visible {
26
- outline: 1px dotted #212121 !important;
27
- outline: 5px auto -webkit-focus-ring-color !important;
28
- }
30
+ @keyframes slide-up {
31
+ from {
32
+ overflow: hidden;
33
+ max-height: @animationContentMaxHeight;
34
+ opacity: 1;
35
+ visibility: visible;
36
+ }
29
37
 
30
- .accessibility-accordion-tab {
31
- outline: none;
32
- }
38
+ to {
39
+ overflow: hidden;
40
+ max-height: 0;
41
+ opacity: 0;
42
+ visibility: hidden;
43
+ }
44
+ }
33
45
 
34
- .accessibility-accordion-tab:focus-visible {
35
- outline: 1px dotted #212121 !important;
36
- outline: 5px auto -webkit-focus-ring-color !important;
37
- }
46
+ .tabs-block {
47
+ .remove-menu.active {
48
+ overflow: revert; /* needed for edit double click to modify title to remove scrollbar */
38
49
  }
50
+
39
51
  color: @tabsBlockColor;
40
52
 
41
53
  > .styled {
@@ -91,6 +103,24 @@
91
103
  }
92
104
  }
93
105
  }
106
+
107
+ @media not (prefers-reduced-motion) {
108
+ .ui.accordion .title ~ .content.RRT__panel {
109
+ display: block;
110
+ padding: 0;
111
+ animation: slide-up @animationDuration linear both;
112
+ will-change: max-height, overflow, opacity;
113
+ }
114
+
115
+ .tab-name {
116
+ padding: @tabAccordionContentPadding;
117
+ }
118
+
119
+ .ui.accordion .title ~ .content.RRT__panel.active {
120
+ animation: slide-down @animationDuration linear both;
121
+ }
122
+ }
123
+
94
124
  @media print {
95
125
  .ui.tab {
96
126
  display: block !important;
@@ -5,6 +5,9 @@
5
5
  @tabsBlockColor: var(--text-color, #000);
6
6
  @verticalPadding: 1rem;
7
7
  @horizontalPadding: 1rem;
8
+ @animationDuration: 0.5s;
9
+ @tabAccordionContentPadding: 1rem;
10
+ @animationContentMaxHeight: 1000px;
8
11
 
9
12
  /* Tab pane */
10
13
  @tabPanePadding: @verticalPadding @horizontalPadding;