@nascentdigital/funnel-ui 4.6.7 → 5.0.2

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 (63) hide show
  1. package/dist/client/fields/EmbeddedVideo/EmbeddedVideo.d.ts +2 -2
  2. package/dist/client/fields/EmbeddedVideo/EmbeddedVideo.js +3 -3
  3. package/dist/client/fields/EmbeddedVideo/vimeo/VimeoVideo.d.ts +3 -3
  4. package/dist/client/fields/EmbeddedVideo/vimeo/VimeoVideo.js +4 -3
  5. package/dist/client/fields/EmbeddedVideo/youtube/YoutubeVideo.d.ts +3 -3
  6. package/dist/client/fields/EmbeddedVideo/youtube/YoutubeVideo.js +4 -3
  7. package/dist/client/fields/LazyVideo.d.ts +5 -1
  8. package/dist/client/fields/LazyVideo.js +6 -4
  9. package/dist/client/hooks/useTouch.js +1 -0
  10. package/dist/client/interaction/paginator/Paginator.js +0 -1
  11. package/dist/server/blocks/Block.d.ts +87 -15
  12. package/dist/server/blocks/Block.js +785 -60
  13. package/dist/server/blocks/MediaLayout.d.ts +26 -10
  14. package/dist/server/blocks/MediaLayout.js +14 -23
  15. package/dist/server/blocks/Message.js +2 -2
  16. package/dist/server/blocks/RelatedPages.js +4 -4
  17. package/dist/server/blocks/index.d.ts +0 -1
  18. package/dist/server/blocks/index.js +0 -1
  19. package/dist/server/fields/Media.d.ts +50 -22
  20. package/dist/server/fields/Media.js +75 -48
  21. package/dist/server/fields/Visual.d.ts +6 -2
  22. package/dist/server/fields/Visual.js +9 -5
  23. package/dist/server/index.d.ts +1 -0
  24. package/dist/server/index.js +1 -0
  25. package/dist/server/layouts/accordion/Accordion.d.ts +21 -0
  26. package/dist/server/layouts/accordion/Accordion.js +66 -0
  27. package/dist/server/layouts/accordion/AccordionContainer.d.ts +5 -0
  28. package/dist/server/layouts/accordion/AccordionContainer.js +18 -0
  29. package/dist/server/layouts/accordion/AccordionContext.d.ts +7 -0
  30. package/dist/server/layouts/accordion/AccordionContext.js +7 -0
  31. package/dist/server/layouts/accordion/AccordionExpander.d.ts +9 -0
  32. package/dist/server/layouts/accordion/AccordionExpander.js +72 -0
  33. package/dist/server/layouts/accordion/AccordionItem.d.ts +8 -0
  34. package/dist/server/layouts/accordion/AccordionItem.js +22 -0
  35. package/dist/server/layouts/accordion/AccordionLayout.d.ts +7 -0
  36. package/dist/server/layouts/accordion/AccordionLayout.js +26 -0
  37. package/dist/server/layouts/accordion/AccordionOptions.d.ts +3 -0
  38. package/dist/server/layouts/accordion/AccordionOptions.js +2 -0
  39. package/dist/server/layouts/accordion/index.d.ts +3 -0
  40. package/dist/server/layouts/accordion/index.js +19 -0
  41. package/dist/server/layouts/accordion/useAccordion.d.ts +1 -0
  42. package/dist/server/layouts/accordion/useAccordion.js +34 -0
  43. package/dist/server/layouts/index.d.ts +2 -1
  44. package/dist/server/layouts/index.js +2 -1
  45. package/dist/server/panels/BlockPanel.d.ts +14 -80
  46. package/dist/server/panels/BlockPanel.js +46 -707
  47. package/dist/server/panels/ListPanel.js +6 -3
  48. package/dist/server/panels/MessagePanel.js +33 -33
  49. package/dist/server/panels/VisualPanel.d.ts +58 -10
  50. package/dist/server/panels/VisualPanel.js +155 -79
  51. package/dist/server/schema/ListPanelLayout.d.ts +1 -0
  52. package/dist/server/schema/ListPanelLayout.js +1 -0
  53. package/dist/styles/blocks/Block-layout.css +81 -80
  54. package/dist/styles/blocks/Editorial.css +2 -2
  55. package/dist/styles/blocks/Form.css +2 -2
  56. package/dist/styles/blocks/MediaLayout.css +1 -1
  57. package/dist/styles/components/container.css +3 -24
  58. package/dist/styles/layouts/Accordion.css +29 -0
  59. package/dist/styles/layouts/_index.css +2 -1
  60. package/dist/styles/panels/VisualPanel.css +2 -1
  61. package/package.json +2 -2
  62. package/dist/server/blocks/Editorial.d.ts +0 -33
  63. package/dist/server/blocks/Editorial.js +0 -80
@@ -55,11 +55,14 @@ function ListPanel({ as = 'ul', className, panel, layout, items, layoutConfigs =
55
55
  case 'verticalStack':
56
56
  layoutComponent = ((0, jsx_runtime_1.jsx)(layouts_1.StackLayout, Object.assign({ as: as, direction: "vertical" }, verticalStack, { children: itemsComponent })));
57
57
  break;
58
+ case 'accordion':
59
+ layoutComponent = ((0, jsx_runtime_1.jsx)(layouts_1.AccordionLayout, { children: itemsComponent }));
60
+ break;
58
61
  }
59
62
  // render
60
- return ((0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)(className, '@container nd-ListPanel',
61
- // base layout
62
- BlockPanel_1.BlockPanel.getClassNames({ panel })), children: (0, jsx_runtime_1.jsx)("div", { className: "nd-BlockPanel-content nd-ListPanel-content", children: layoutComponent }) }));
63
+ return ((0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)('nd-ListPanel-wrap', BlockPanel_1.BlockPanel.getWrapClassName(), BlockPanel_1.BlockPanel.getFullBleedClassNames({ panel })), children: (0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)(className, '@container nd-ListPanel',
64
+ // base layout
65
+ BlockPanel_1.BlockPanel.getClassNames({ panel })), children: (0, jsx_runtime_1.jsx)("div", { className: "nd-BlockPanel-content nd-ListPanel-content", children: layoutComponent }) }) }));
63
66
  }
64
67
  // extension
65
68
  (function (ListPanel) {
@@ -28,40 +28,40 @@ function MessagePanel({ className, panel, titleTag = 'span', title, headlineTag
28
28
  ];
29
29
  }
30
30
  // render
31
- return ((0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)(className, 'nd-MessagePanel',
32
- // base layout
33
- BlockPanel_1.BlockPanel.getClassNames({ panel, alignX, alignY, size, fullbleed, mobileOrder }),
34
- // text-align
35
- textAlign
36
- ? {
37
- 'nd-MessagePanel-textStart': textAlign === 'left',
38
- 'nd-MessagePanel-textCenter': textAlign === 'center',
39
- 'nd-MessagePanel-textEnd': textAlign === 'right'
40
- }
41
- : funnel_core_1.BlockLayout.ResponsiveClassNames.parse({
42
- value: panel.textAlign,
43
- mobile: {
44
- left: 'max-md:nd-MessagePanel-textStart',
45
- center: 'max-md:nd-MessagePanel-textCenter',
46
- right: 'max-md:nd-MessagePanel-textEnd'
47
- },
48
- base: {
49
- left: 'md:nd-MessagePanel-textStart',
50
- center: 'md:nd-MessagePanel-textCenter',
51
- right: 'md:nd-MessagePanel-textEnd'
52
- },
53
- desktop: {
54
- left: 'lg:nd-MessagePanel-textStart',
55
- center: 'lg:nd-MessagePanel-textCenter',
56
- right: 'lg:nd-MessagePanel-textEnd'
31
+ return ((0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)('nd-MessagePanel-wrap', BlockPanel_1.BlockPanel.getWrapClassName(), BlockPanel_1.BlockPanel.getFullBleedClassNames({ panel })), children: (0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)(className, 'nd-MessagePanel',
32
+ // base layout
33
+ BlockPanel_1.BlockPanel.getClassNames({ panel, alignX, alignY, size, fullbleed, mobileOrder }),
34
+ // text-align
35
+ textAlign
36
+ ? {
37
+ 'nd-MessagePanel-textStart': textAlign === 'left',
38
+ 'nd-MessagePanel-textCenter': textAlign === 'center',
39
+ 'nd-MessagePanel-textEnd': textAlign === 'right'
57
40
  }
58
- })), children: (0, jsx_runtime_1.jsxs)("div", { className: "nd-BlockPanel-content nd-MessagePanel-content", children: [!title && !headline && !caption && ctas.length === 0 &&
59
- (0, jsx_runtime_1.jsx)(MessagePanel.Placeholder, {}), title &&
60
- (0, jsx_runtime_1.jsx)(fields_1.Title, { className: "nd-MessagePanel-title", as: titleTag, title: title }), headline &&
61
- (0, jsx_runtime_1.jsx)(fields_1.Headline, { className: "nd-MessagePanel-headline", as: headlineTag, headline: headline }), caption &&
62
- (0, jsx_runtime_1.jsx)(fields_1.Caption, { className: "nd-MessagePanel-caption", as: captionTag, caption: caption }), ctas.length > 0 &&
63
- (0, jsx_runtime_1.jsx)(fields_1.CallToActions, { className: "nd-MessagePanel-ctas", ctas: ctas }), decorator &&
64
- (0, jsx_runtime_1.jsx)("div", { className: "nd-MessagePanel-decorator", children: decorator })] }) }));
41
+ : funnel_core_1.BlockLayout.ResponsiveClassNames.parse({
42
+ value: panel.textAlign,
43
+ mobile: {
44
+ left: 'max-md:nd-MessagePanel-textStart',
45
+ center: 'max-md:nd-MessagePanel-textCenter',
46
+ right: 'max-md:nd-MessagePanel-textEnd'
47
+ },
48
+ base: {
49
+ left: 'md:nd-MessagePanel-textStart',
50
+ center: 'md:nd-MessagePanel-textCenter',
51
+ right: 'md:nd-MessagePanel-textEnd'
52
+ },
53
+ desktop: {
54
+ left: 'lg:nd-MessagePanel-textStart',
55
+ center: 'lg:nd-MessagePanel-textCenter',
56
+ right: 'lg:nd-MessagePanel-textEnd'
57
+ }
58
+ })), children: (0, jsx_runtime_1.jsxs)("div", { className: "nd-BlockPanel-content nd-MessagePanel-content", children: [!title && !headline && !caption && ctas.length === 0 &&
59
+ (0, jsx_runtime_1.jsx)(MessagePanel.Placeholder, {}), title &&
60
+ (0, jsx_runtime_1.jsx)(fields_1.Title, { className: "nd-MessagePanel-title", as: titleTag, title: title }), headline &&
61
+ (0, jsx_runtime_1.jsx)(fields_1.Headline, { className: "nd-MessagePanel-headline", as: headlineTag, headline: headline }), caption &&
62
+ (0, jsx_runtime_1.jsx)(fields_1.Caption, { className: "nd-MessagePanel-caption", as: captionTag, caption: caption }), ctas.length > 0 &&
63
+ (0, jsx_runtime_1.jsx)(fields_1.CallToActions, { className: "nd-MessagePanel-ctas", ctas: ctas }), decorator &&
64
+ (0, jsx_runtime_1.jsx)("div", { className: "nd-MessagePanel-decorator", children: decorator })] }) }) }));
65
65
  }
66
66
  // extension
67
67
  (function (MessagePanel) {
@@ -1,26 +1,50 @@
1
1
  import { BlockLayout, Schema } from '@nascentdigital/funnel-core';
2
2
  import { ReactNode } from 'react';
3
- import { Visual } from '../fields';
3
+ import { Media, Visual } from '../fields';
4
4
  import { Anchor, AspectRatio, ItemAlignment, ItemPosition, ItemSize } from '../schema';
5
5
  import { BlockPanel } from './BlockPanel';
6
- export declare function VisualPanel({ className, panel, visual, visualDecorator, visualLoading, aspect, anchor, alignX, alignY, size, fullbleed, mobileOrder }: VisualPanel.Props): import("react/jsx-runtime").JSX.Element;
6
+ export declare function VisualPanel({ className, panel, visual, visualDecorator, visualLoading, aspect, anchor, controls, autoPlay, loop, mute, alignX, alignY, size, fullbleed, mobileOrder }: VisualPanel.Props): import("react/jsx-runtime").JSX.Element;
7
7
  export declare namespace VisualPanel {
8
8
  type Props = BlockPanel.Props & {
9
9
  className?: string;
10
10
  panel: BlockLayout.Visual;
11
- visual?: Visual.Model;
11
+ visual?: Media.LinkedValue;
12
12
  visualDecorator?: ReactNode;
13
13
  visualLoading?: Visual.Loading;
14
14
  aspect?: AspectRatio;
15
15
  anchor?: Anchor;
16
+ controls?: boolean;
17
+ autoPlay?: boolean;
18
+ loop?: boolean;
19
+ mute?: boolean;
16
20
  };
17
21
  namespace Props {
18
22
  type Configuration = Pick<Props, 'className' | 'visualDecorator' | 'visualLoading'>;
19
23
  }
20
24
  namespace Fields {
21
- const visual: Schema.Optional<Schema.AssetField<Schema.AssetField.LinkedValue.Visual>>;
25
+ const visual: Schema.Optional<Schema.CollectionField<Schema.Collection<{
26
+ image: Schema.AssetField<Schema.AssetField.LinkedValue.Image>;
27
+ mobileImage: Schema.Optional<Schema.AssetField<Schema.AssetField.LinkedValue.Image>>;
28
+ }> | Schema.Collection<{
29
+ video: Schema.ObjectField<{
30
+ type: Schema.EnumField<Schema.EnumField.Options<Media.Video.Source.Type>>;
31
+ local: Schema.Optional<Schema.AssetField<Schema.AssetField.LinkedValue.Video>>;
32
+ remote: Schema.Optional<Schema.EmbeddedVideoField>;
33
+ }>;
34
+ cover: Schema.Optional<Schema.AssetField<Schema.AssetField.LinkedValue.Image>>;
35
+ }>>>;
22
36
  const all: {
23
- visual: Schema.Optional<Schema.AssetField<Schema.AssetField.LinkedValue.Visual>>;
37
+ visual: Schema.Optional<Schema.CollectionField<Schema.Collection<{
38
+ image: Schema.AssetField<Schema.AssetField.LinkedValue.Image>;
39
+ mobileImage: Schema.Optional<Schema.AssetField<Schema.AssetField.LinkedValue.Image>>;
40
+ }> | Schema.Collection<{
41
+ video: Schema.ObjectField<{
42
+ type: Schema.EnumField<Schema.EnumField.Options<Media.Video.Source.Type>>;
43
+ local: Schema.Optional<Schema.AssetField<Schema.AssetField.LinkedValue.Video>>;
44
+ remote: Schema.Optional<Schema.EmbeddedVideoField>;
45
+ }>;
46
+ cover: Schema.Optional<Schema.AssetField<Schema.AssetField.LinkedValue.Image>>;
47
+ }>>>;
24
48
  };
25
49
  }
26
50
  namespace VisualPosition {
@@ -28,7 +52,7 @@ export declare namespace VisualPanel {
28
52
  type Schema = typeof schema;
29
53
  }
30
54
  namespace Config {
31
- type Key<TPrefix extends string = string> = Key.Aspect<TPrefix> | Key.Anchor<TPrefix> | Key.HorizontalAlign<TPrefix> | Key.Width<TPrefix>;
55
+ type Key<TPrefix extends string = string> = Key.Aspect<TPrefix> | Key.Anchor<TPrefix> | Key.HorizontalAlign<TPrefix> | Key.Width<TPrefix> | Key.Controls<TPrefix> | Key.AutoPlay<TPrefix> | Key.Loop<TPrefix> | Key.Mute<TPrefix>;
32
56
  namespace Key {
33
57
  type Aspect<TPrefix extends string> = `${TPrefix}Aspect`;
34
58
  function aspect<TPrefix extends string>(prefix: TPrefix): Aspect<TPrefix>;
@@ -38,23 +62,47 @@ export declare namespace VisualPanel {
38
62
  function width<TPrefix extends string>(prefix: TPrefix): Width<TPrefix>;
39
63
  type HorizontalAlign<TPrefix extends string> = `${TPrefix}HorizontalAlign`;
40
64
  function horizontalAlign<TPrefix extends string>(prefix: TPrefix): HorizontalAlign<TPrefix>;
65
+ type Controls<TPrefix extends string> = `${TPrefix}Controls`;
66
+ function controls<TPrefix extends string>(prefix: TPrefix): Controls<TPrefix>;
67
+ type AutoPlay<TPrefix extends string> = `${TPrefix}AutoPlay`;
68
+ function autoPlay<TPrefix extends string>(prefix: TPrefix): AutoPlay<TPrefix>;
69
+ type Loop<TPrefix extends string> = `${TPrefix}Loop`;
70
+ function loop<TPrefix extends string>(prefix: TPrefix): Loop<TPrefix>;
71
+ type Mute<TPrefix extends string> = `${TPrefix}Mute`;
72
+ function mute<TPrefix extends string>(prefix: TPrefix): Mute<TPrefix>;
41
73
  }
42
74
  type Keys<TPrefix extends string> = {
43
75
  aspect: Key.Aspect<TPrefix>;
44
76
  anchor: Key.Anchor<TPrefix>;
45
77
  width: Key.Width<TPrefix>;
46
78
  horizontalAlign: Key.HorizontalAlign<TPrefix>;
79
+ controls: Key.Controls<TPrefix>;
80
+ autoPlay: Key.AutoPlay<TPrefix>;
81
+ loop: Key.Loop<TPrefix>;
82
+ mute: Key.Mute<TPrefix>;
47
83
  };
48
84
  function getKeys<TPrefix extends string>(prefix: TPrefix): Keys<TPrefix>;
49
- type Entries<TPrefix extends string> = Record<Key.Aspect<TPrefix>, AspectRatio.Schema> & Record<Key.Width<TPrefix>, ItemSize.Schema> & Record<Key.Anchor<TPrefix>, Anchor.Schema> & Record<Key.HorizontalAlign<TPrefix>, ItemAlignment.Horizontal.Schema>;
85
+ type NormalizedEntries = {
86
+ aspect: AspectRatio.Schema;
87
+ anchor: Anchor.Schema;
88
+ width: ItemSize.Schema;
89
+ horizontalAlign: ItemAlignment.Horizontal.Schema;
90
+ controls: Schema.BooleanField;
91
+ autoPlay: Schema.BooleanField;
92
+ loop: Schema.BooleanField;
93
+ mute: Schema.BooleanField;
94
+ };
95
+ type Entries<TPrefix extends string> = {
96
+ [TKey in keyof NormalizedEntries as Keys<TPrefix>[TKey]]: NormalizedEntries[TKey];
97
+ };
50
98
  }
51
99
  namespace GetConfig {
52
- type ConfigSchema<TPrefix extends string> = Record<Config.Key.Aspect<TPrefix>, AspectRatio.Schema> & Record<Config.Key.Anchor<TPrefix>, Anchor.Schema> & Record<Config.Key.Width<TPrefix>, ItemSize.Schema> & Record<Config.Key.HorizontalAlign<TPrefix>, ItemAlignment.Horizontal.Schema>;
100
+ type ConfigSchema<TPrefix extends string> = Record<Config.Key.Aspect<TPrefix>, AspectRatio.Schema> & Record<Config.Key.Anchor<TPrefix>, Anchor.Schema> & Record<Config.Key.Width<TPrefix>, ItemSize.Schema> & Record<Config.Key.HorizontalAlign<TPrefix>, ItemAlignment.Horizontal.Schema> & Record<Config.Key.Controls<TPrefix>, Schema.BooleanField> & Record<Config.Key.AutoPlay<TPrefix>, Schema.BooleanField> & Record<Config.Key.Loop<TPrefix>, Schema.BooleanField> & Record<Config.Key.Mute<TPrefix>, Schema.BooleanField>;
53
101
  type ConfigData<TPrefix extends string> = Schema.Block.Data.ForConfig<ConfigSchema<TPrefix>>;
54
102
  type Position = 'x' | 'y' | 'z';
55
103
  type Args<TPrefix extends string> = {
56
104
  visualKey: TPrefix;
57
- visual?: Schema.Field.Data<Schema.AssetField> | Schema.Field.LinkedData<Schema.AssetField>;
105
+ visual?: Schema.Field.Data<Media.Schema> | Schema.Field.LinkedData<Media.Schema>;
58
106
  config?: Partial<ConfigData<TPrefix>>;
59
107
  flexDirection?: BlockPanel.Slots.FlexDirection;
60
108
  };
@@ -64,6 +112,6 @@ export declare namespace VisualPanel {
64
112
  defaultConfig: Partial<ConfigData<TPrefix>>;
65
113
  };
66
114
  }
67
- function getConfig<TPrefix extends string>({ visualKey, visual: visualData, config, flexDirection }: GetConfig.Args<TPrefix>): GetConfig.Result<TPrefix>;
115
+ function getConfig<TPrefix extends string>({ visualKey, visual: visualData, config: configRaw, flexDirection }: GetConfig.Args<TPrefix>): GetConfig.Result<TPrefix>;
68
116
  function Placeholder(): import("react/jsx-runtime").JSX.Element;
69
117
  }
@@ -11,68 +11,68 @@ const fields_1 = require("../fields");
11
11
  const schema_1 = require("../schema");
12
12
  const BlockPanel_1 = require("./BlockPanel");
13
13
  // component
14
- function VisualPanel({ className, panel, visual, visualDecorator, visualLoading, aspect, anchor = 'center', alignX, alignY, size, fullbleed, mobileOrder }) {
14
+ function VisualPanel({ className, panel, visual, visualDecorator, visualLoading, aspect, anchor = 'center', controls, autoPlay, loop, mute, alignX, alignY, size, fullbleed, mobileOrder }) {
15
15
  // render
16
- return ((0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)(className, 'nd-VisualPanel',
17
- // base layout
18
- BlockPanel_1.BlockPanel.getClassNames({ panel, alignX, alignY, size, fullbleed, mobileOrder }),
19
- // aspect
20
- aspect
21
- ? {
22
- 'nd-VisualPanel-aspect-auto': aspect === 'auto',
23
- 'nd-VisualPanel-aspect-square': aspect === 'square',
24
- 'nd-VisualPanel-aspect-phone': aspect === 'phone',
25
- 'nd-VisualPanel-aspect-tv': aspect === 'tv',
26
- 'nd-VisualPanel-aspect-widescreen': aspect === 'widescreen',
27
- 'nd-VisualPanel-aspect-cinema': aspect === 'cinema'
28
- }
29
- : funnel_core_1.BlockLayout.ResponsiveClassNames.parse({
30
- value: panel.aspectRatio,
31
- mobile: {
32
- auto: 'max-md:nd-VisualPanel-aspect-auto',
33
- square: 'max-md:nd-VisualPanel-aspect-square',
34
- phone: 'max-md:nd-VisualPanel-aspect-phone',
35
- tv: 'max-md:nd-VisualPanel-aspect-tv',
36
- widescreen: 'max-md:nd-VisualPanel-aspect-widescreen',
37
- cinema: 'max-md:nd-VisualPanel-aspect-cinema'
38
- },
39
- base: {
40
- auto: 'md:nd-VisualPanel-aspect-auto',
41
- square: 'md:nd-VisualPanel-aspect-square',
42
- phone: 'md:nd-VisualPanel-aspect-phone',
43
- tv: 'md:nd-VisualPanel-aspect-tv',
44
- widescreen: 'md:nd-VisualPanel-aspect-widescreen',
45
- cinema: 'md:nd-VisualPanel-aspect-cinema'
46
- },
47
- desktop: {
48
- auto: 'lg:nd-VisualPanel-aspect-auto',
49
- square: 'lg:nd-VisualPanel-aspect-square',
50
- phone: 'lg:nd-VisualPanel-aspect-phone',
51
- tv: 'lg:nd-VisualPanel-aspect-tv',
52
- widescreen: 'lg:nd-VisualPanel-aspect-widescreen',
53
- cinema: 'lg:nd-VisualPanel-aspect-cinema'
16
+ return ((0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)('nd-VisualPanel-wrap', BlockPanel_1.BlockPanel.getWrapClassName(), BlockPanel_1.BlockPanel.getFullBleedClassNames({ panel })), children: (0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)(className, 'nd-VisualPanel',
17
+ // base layout
18
+ BlockPanel_1.BlockPanel.getClassNames({ panel, alignX, alignY, size, fullbleed, mobileOrder }),
19
+ // aspect
20
+ aspect
21
+ ? {
22
+ 'nd-VisualPanel-aspect-auto': aspect === 'auto',
23
+ 'nd-VisualPanel-aspect-square': aspect === 'square',
24
+ 'nd-VisualPanel-aspect-phone': aspect === 'phone',
25
+ 'nd-VisualPanel-aspect-tv': aspect === 'tv',
26
+ 'nd-VisualPanel-aspect-widescreen': aspect === 'widescreen',
27
+ 'nd-VisualPanel-aspect-cinema': aspect === 'cinema'
54
28
  }
55
- }),
56
- // anchor
57
- {
58
- 'nd-VisualPanel-anchor-center': anchor === 'center',
59
- 'nd-VisualPanel-anchor-top': anchor === 'top',
60
- 'nd-VisualPanel-anchor-bottom': anchor === 'bottom',
61
- 'nd-VisualPanel-anchor-left': anchor === 'left',
62
- 'nd-VisualPanel-anchor-right': anchor === 'right'
63
- }), children: (0, jsx_runtime_1.jsxs)("div", { className: "nd-BlockPanel-content nd-VisualPanel-content", children: [visual
64
- ?
65
- (0, jsx_runtime_1.jsx)(fields_1.Visual, { className: "nd-VisualPanel-visual", visual: visual, loading: visualLoading })
66
- :
67
- (0, jsx_runtime_1.jsx)(VisualPanel.Placeholder, {}), visualDecorator &&
68
- (0, jsx_runtime_1.jsx)("div", { className: "nd-VisualPanel-decorator", children: visualDecorator })] }) }));
29
+ : funnel_core_1.BlockLayout.ResponsiveClassNames.parse({
30
+ value: panel.aspectRatio,
31
+ mobile: {
32
+ auto: 'max-md:nd-VisualPanel-aspect-auto',
33
+ square: 'max-md:nd-VisualPanel-aspect-square',
34
+ phone: 'max-md:nd-VisualPanel-aspect-phone',
35
+ tv: 'max-md:nd-VisualPanel-aspect-tv',
36
+ widescreen: 'max-md:nd-VisualPanel-aspect-widescreen',
37
+ cinema: 'max-md:nd-VisualPanel-aspect-cinema'
38
+ },
39
+ base: {
40
+ auto: 'md:nd-VisualPanel-aspect-auto',
41
+ square: 'md:nd-VisualPanel-aspect-square',
42
+ phone: 'md:nd-VisualPanel-aspect-phone',
43
+ tv: 'md:nd-VisualPanel-aspect-tv',
44
+ widescreen: 'md:nd-VisualPanel-aspect-widescreen',
45
+ cinema: 'md:nd-VisualPanel-aspect-cinema'
46
+ },
47
+ desktop: {
48
+ auto: 'lg:nd-VisualPanel-aspect-auto',
49
+ square: 'lg:nd-VisualPanel-aspect-square',
50
+ phone: 'lg:nd-VisualPanel-aspect-phone',
51
+ tv: 'lg:nd-VisualPanel-aspect-tv',
52
+ widescreen: 'lg:nd-VisualPanel-aspect-widescreen',
53
+ cinema: 'lg:nd-VisualPanel-aspect-cinema'
54
+ }
55
+ }),
56
+ // anchor
57
+ {
58
+ 'nd-VisualPanel-anchor-center': anchor === 'center',
59
+ 'nd-VisualPanel-anchor-top': anchor === 'top',
60
+ 'nd-VisualPanel-anchor-bottom': anchor === 'bottom',
61
+ 'nd-VisualPanel-anchor-left': anchor === 'left',
62
+ 'nd-VisualPanel-anchor-right': anchor === 'right'
63
+ }), children: (0, jsx_runtime_1.jsxs)("div", { className: "nd-BlockPanel-content nd-VisualPanel-content", children: [fields_1.Media.LinkedValue.filter(visual)
64
+ ?
65
+ (0, jsx_runtime_1.jsx)(fields_1.Media, { className: "nd-VisualPanel-visual", media: visual, loading: visualLoading, controls: controls, autoPlay: autoPlay, loop: loop, mute: mute })
66
+ :
67
+ (0, jsx_runtime_1.jsx)(VisualPanel.Placeholder, {}), visualDecorator &&
68
+ (0, jsx_runtime_1.jsx)("div", { className: "nd-VisualPanel-decorator", children: visualDecorator })] }) }) }));
69
69
  }
70
70
  // extension
71
71
  (function (VisualPanel) {
72
72
  // fields
73
73
  let Fields;
74
74
  (function (Fields) {
75
- Fields.visual = fields_1.Visual.schema.optional();
75
+ Fields.visual = fields_1.Media.schema.optional();
76
76
  Fields.all = {
77
77
  visual: Fields.visual
78
78
  };
@@ -108,6 +108,22 @@ function VisualPanel({ className, panel, visual, visualDecorator, visualLoading,
108
108
  return `${prefix}HorizontalAlign`;
109
109
  }
110
110
  Key.horizontalAlign = horizontalAlign;
111
+ function controls(prefix) {
112
+ return `${prefix}Controls`;
113
+ }
114
+ Key.controls = controls;
115
+ function autoPlay(prefix) {
116
+ return `${prefix}AutoPlay`;
117
+ }
118
+ Key.autoPlay = autoPlay;
119
+ function loop(prefix) {
120
+ return `${prefix}Loop`;
121
+ }
122
+ Key.loop = loop;
123
+ function mute(prefix) {
124
+ return `${prefix}Mute`;
125
+ }
126
+ Key.mute = mute;
111
127
  })(Key = Config.Key || (Config.Key = {}));
112
128
  function getKeys(prefix) {
113
129
  return {
@@ -115,29 +131,53 @@ function VisualPanel({ className, panel, visual, visualDecorator, visualLoading,
115
131
  anchor: `${prefix}Anchor`,
116
132
  width: `${prefix}Width`,
117
133
  horizontalAlign: `${prefix}HorizontalAlign`,
134
+ controls: `${prefix}Controls`,
135
+ autoPlay: `${prefix}AutoPlay`,
136
+ loop: `${prefix}Loop`,
137
+ mute: `${prefix}Mute`
118
138
  };
119
139
  }
120
140
  Config.getKeys = getKeys;
121
141
  })(Config = VisualPanel.Config || (VisualPanel.Config = {}));
122
- function getConfig({ visualKey, visual: visualData, config = {}, flexDirection }) {
123
- var _a, _b, _c, _d, _e, _f, _g;
124
- // resolve values
142
+ function getConfig({ visualKey, visual: visualData, config: configRaw = {}, flexDirection }) {
143
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
144
+ // helpers
125
145
  const keys = Config.getKeys(visualKey);
146
+ const getConfigValue = (key) => {
147
+ var _a;
148
+ return (_a = configRaw[keys[key]]) === null || _a === void 0 ? void 0 : _a.value;
149
+ };
150
+ // resolve values
126
151
  const defaultAspect = 'auto';
127
152
  const defaultAnchor = 'center';
128
- let aspect = (_b = (_a = config[keys.aspect]) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : defaultAspect;
129
- let anchor = (_d = (_c = config[keys.anchor]) === null || _c === void 0 ? void 0 : _c.value) !== null && _d !== void 0 ? _d : defaultAnchor;
153
+ let aspect = (_a = getConfigValue('aspect')) !== null && _a !== void 0 ? _a : defaultAspect;
154
+ let anchor = (_b = getConfigValue('anchor')) !== null && _b !== void 0 ? _b : defaultAnchor;
130
155
  const visual = visualData === null || visualData === void 0 ? void 0 : visualData.value;
131
156
  // return immediately if there's no visual
132
- if (!visual || !funnel_core_1.Schema.AssetField.LinkedValue.Visual.filter(visual)) {
157
+ if (!visual || !fields_1.Media.LinkedValue.filter(visual)) {
133
158
  return {
134
159
  configSchema: {},
135
160
  config: {},
136
161
  defaultConfig: {}
137
162
  };
138
163
  }
164
+ // try to extract dimensions from media
165
+ let isVideo = false;
166
+ let width = undefined;
167
+ let height = undefined;
168
+ if (fields_1.Media.LinkedValue.isImage(visual)) {
169
+ const dimensions = (_g = (_f = (_e = (_d = (_c = visual.fields) === null || _c === void 0 ? void 0 : _c.image) === null || _d === void 0 ? void 0 : _d.value) === null || _e === void 0 ? void 0 : _e.metadata) === null || _f === void 0 ? void 0 : _f.dimensions) !== null && _g !== void 0 ? _g : {};
170
+ width = dimensions === null || dimensions === void 0 ? void 0 : dimensions.width;
171
+ height = dimensions === null || dimensions === void 0 ? void 0 : dimensions.height;
172
+ }
173
+ else if (fields_1.Media.LinkedValue.isVideo(visual)) {
174
+ const { local, remote } = (_k = (_j = (_h = visual.fields) === null || _h === void 0 ? void 0 : _h.video) === null || _j === void 0 ? void 0 : _j.value) !== null && _k !== void 0 ? _k : {};
175
+ const { dimensions } = (_o = (_m = (_l = local === null || local === void 0 ? void 0 : local.value) === null || _l === void 0 ? void 0 : _l.metadata) !== null && _m !== void 0 ? _m : remote === null || remote === void 0 ? void 0 : remote.value) !== null && _o !== void 0 ? _o : {};
176
+ width = dimensions === null || dimensions === void 0 ? void 0 : dimensions.width;
177
+ height = dimensions === null || dimensions === void 0 ? void 0 : dimensions.height;
178
+ isVideo = true;
179
+ }
139
180
  // determine is visual is an existing aspect ratio (and switch aspect to auto if it matches)
140
- const { dimensions: { width, height } = {} } = (_e = visual.metadata) !== null && _e !== void 0 ? _e : {};
141
181
  const sourceAspectRatio = width && height
142
182
  ? width / height
143
183
  : undefined;
@@ -148,16 +188,46 @@ function VisualPanel({ className, panel, visual, visualDecorator, visualLoading,
148
188
  aspect = 'auto';
149
189
  }
150
190
  // create schema (drop matched aspect if we need to)
151
- const configSchema = {
152
- [keys.aspect]: matchedAspect
191
+ const configSchema = Object.assign({ [keys.aspect]: matchedAspect
153
192
  ? schema_1.AspectRatio.schema.removeOption(matchedAspect)
154
- : schema_1.AspectRatio.schema,
155
- [keys.anchor]: aspect === 'auto' ? undefined : schema_1.Anchor.schema,
156
- [keys.horizontalAlign]: schema_1.ItemAlignment.Horizontal.schema,
157
- [keys.width]: schema_1.ItemSize.schema
158
- };
193
+ : schema_1.AspectRatio.schema, [keys.anchor]: aspect === 'auto' ? undefined : schema_1.Anchor.schema, [keys.horizontalAlign]: schema_1.ItemAlignment.Horizontal.schema, [keys.width]: schema_1.ItemSize.schema }, (isVideo
194
+ ? {
195
+ [keys.controls]: funnel_core_1.Schema.Field.boolean({
196
+ name: 'Show Controls',
197
+ description: 'Display video controls so views can play/pause/seek content.',
198
+ defaultValue: true,
199
+ semantics: 'toggle'
200
+ }),
201
+ [keys.autoPlay]: funnel_core_1.Schema.Field.boolean({
202
+ name: 'Autoplay',
203
+ description: 'Video will automatically play once it\'s ready.',
204
+ defaultValue: false,
205
+ semantics: 'toggle'
206
+ }),
207
+ [keys.loop]: funnel_core_1.Schema.Field.boolean({
208
+ name: 'Loop',
209
+ description: 'Video will loop forever when enabled.',
210
+ defaultValue: false,
211
+ semantics: 'toggle'
212
+ }),
213
+ [keys.mute]: funnel_core_1.Schema.Field.boolean({
214
+ name: 'Mute',
215
+ description: 'Audio will be silenced.',
216
+ defaultValue: true,
217
+ semantics: 'toggle'
218
+ })
219
+ }
220
+ : {}));
159
221
  const defaultPanelWidth = 'full';
160
- let panelWidth = (_g = (_f = config[keys.width]) === null || _f === void 0 ? void 0 : _f.value) !== null && _g !== void 0 ? _g : defaultPanelWidth;
222
+ let panelWidth = (_p = getConfigValue('width')) !== null && _p !== void 0 ? _p : defaultPanelWidth;
223
+ const controlsDefault = false;
224
+ const controls = (_q = getConfigValue('controls')) !== null && _q !== void 0 ? _q : controlsDefault;
225
+ const autoPlayDefault = false;
226
+ const autoPlay = (_r = getConfigValue('autoPlay')) !== null && _r !== void 0 ? _r : autoPlayDefault;
227
+ const loopDefault = false;
228
+ const loop = (_s = getConfigValue('loop')) !== null && _s !== void 0 ? _s : loopDefault;
229
+ const muteDefault = false;
230
+ const mute = (_t = getConfigValue('mute')) !== null && _t !== void 0 ? _t : muteDefault;
161
231
  // reduce anchor to options that are allowed (vertical vs horizontal cropping)
162
232
  if (sourceAspectRatio && aspect !== 'auto') {
163
233
  // coerce anchor
@@ -188,16 +258,22 @@ function VisualPanel({ className, panel, visual, visualDecorator, visualLoading,
188
258
  // return result
189
259
  return {
190
260
  configSchema: configSchema,
191
- config: {
192
- [keys.aspect]: funnel_core_1.Schema.EnumField.Value.toData(aspect),
193
- [keys.anchor]: aspect === 'auto' ? undefined : funnel_core_1.Schema.EnumField.Value.toData(anchor),
194
- [keys.width]: funnel_core_1.Schema.EnumField.Value.toData(panelWidth),
195
- },
196
- defaultConfig: {
197
- [keys.aspect]: funnel_core_1.Schema.EnumField.Value.toData(defaultAspect),
198
- [keys.anchor]: aspect === 'auto' ? undefined : funnel_core_1.Schema.EnumField.Value.toData(defaultAnchor),
199
- [keys.width]: funnel_core_1.Schema.EnumField.Value.toData(defaultPanelWidth),
200
- }
261
+ config: Object.assign({ [keys.aspect]: funnel_core_1.Schema.EnumField.Value.toData(aspect), [keys.anchor]: aspect === 'auto' ? undefined : funnel_core_1.Schema.EnumField.Value.toData(anchor), [keys.width]: funnel_core_1.Schema.EnumField.Value.toData(panelWidth) }, (isVideo
262
+ ? {
263
+ [keys.controls]: funnel_core_1.Schema.BooleanField.Value.toData(controls),
264
+ [keys.autoPlay]: funnel_core_1.Schema.BooleanField.Value.toData(autoPlay),
265
+ [keys.loop]: funnel_core_1.Schema.BooleanField.Value.toData(loop),
266
+ [keys.mute]: funnel_core_1.Schema.BooleanField.Value.toData(mute)
267
+ }
268
+ : {})),
269
+ defaultConfig: Object.assign({ [keys.aspect]: funnel_core_1.Schema.EnumField.Value.toData(defaultAspect), [keys.anchor]: aspect === 'auto' ? undefined : funnel_core_1.Schema.EnumField.Value.toData(defaultAnchor), [keys.width]: funnel_core_1.Schema.EnumField.Value.toData(defaultPanelWidth) }, (isVideo
270
+ ? {
271
+ [keys.controls]: funnel_core_1.Schema.BooleanField.Value.toData(controlsDefault),
272
+ [keys.autoPlay]: funnel_core_1.Schema.BooleanField.Value.toData(autoPlayDefault),
273
+ [keys.loop]: funnel_core_1.Schema.BooleanField.Value.toData(loopDefault),
274
+ [keys.mute]: funnel_core_1.Schema.BooleanField.Value.toData(muteDefault)
275
+ }
276
+ : {}))
201
277
  };
202
278
  }
203
279
  VisualPanel.getConfig = getConfig;
@@ -36,5 +36,6 @@ export declare namespace ListPanelLayout {
36
36
  masonry: Masonry;
37
37
  verticalStack: Omit<Stack, 'direction'>;
38
38
  bento: {};
39
+ accordion: {};
39
40
  };
40
41
  }
@@ -15,6 +15,7 @@ var ListPanelLayout;
15
15
  bento: { name: 'Bento' },
16
16
  brick: { name: 'Brick' },
17
17
  brickFlipped: { name: 'Brick flipped' },
18
+ accordion: { name: 'Accordion' },
18
19
  carousel: { name: 'Carousel' }
19
20
  };
20
21
  ListPanelLayout.schema = funnel_core_1.Schema.Field.enumeration({