@nascentdigital/funnel-ui 4.6.0 → 4.6.7

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.
@@ -1,8 +1,9 @@
1
1
  import { Schema } from '@nascentdigital/funnel-core';
2
2
  import { HTMLAttributes } from 'react';
3
- export declare function LazyVideo({ className, video: asset, ...props }: LazyVideo.Props): import("react/jsx-runtime").JSX.Element | null;
3
+ export declare function LazyVideo({ className, video: asset, poster, ...props }: LazyVideo.Props): import("react/jsx-runtime").JSX.Element | null;
4
4
  export declare namespace LazyVideo {
5
5
  type Props = Omit<HTMLAttributes<HTMLImageElement> & HTMLAttributes<HTMLVideoElement>, 'children'> & {
6
6
  video?: Schema.AssetField.LinkedValue.Video;
7
+ poster?: string;
7
8
  };
8
9
  }
@@ -23,7 +23,7 @@ const react_2 = require("react");
23
23
  const hooks_1 = require("../hooks");
24
24
  // component
25
25
  function LazyVideo(_a) {
26
- var { className, video: asset } = _a, props = __rest(_a, ["className", "video"]);
26
+ var { className, video: asset, poster } = _a, props = __rest(_a, ["className", "video", "poster"]);
27
27
  // bind state + refs
28
28
  const { type, url, metadata: { crop, dimensions: { width, height } = {}, blurHash } = {} } = asset !== null && asset !== void 0 ? asset : {};
29
29
  const [state, setState] = (0, react_2.useState)('uninitialized');
@@ -95,6 +95,6 @@ function LazyVideo(_a) {
95
95
  '--_nd-visual-native-width': width ? `${width}` : '1',
96
96
  '--_nd-visual-native-height': height ? `${height}` : '1'
97
97
  }, children: (0, jsx_runtime_1.jsxs)("div", { className: "nd-LazyVideo-content", children: [blurHash &&
98
- (0, jsx_runtime_1.jsx)("canvas", { ref: blurCanvasRef, className: "nd-LazyVideo-blurHash", width: 32, height: 32, draggable: false }), (0, jsx_runtime_1.jsxs)("video", { ref: videoRef, className: (0, classnames_1.default)('nd-LazyVideo-video'), preload: "none", autoPlay: true, muted: true, loop: true, playsInline: true, children: [state !== 'uninitialized' &&
98
+ (0, jsx_runtime_1.jsx)("canvas", { ref: blurCanvasRef, className: "nd-LazyVideo-blurHash", width: 32, height: 32, draggable: false }), (0, jsx_runtime_1.jsxs)("video", { ref: videoRef, className: (0, classnames_1.default)('nd-LazyVideo-video'), preload: "none", autoPlay: true, muted: true, loop: true, playsInline: true, poster: poster, children: [state !== 'uninitialized' &&
99
99
  (0, jsx_runtime_1.jsx)("source", { src: url, type: type }), "Your browser does not support the video content."] })] }) })));
100
100
  }
@@ -1,6 +1,6 @@
1
1
  import { Callback, Duration, Transform } from '@nascentdigital/funnel-core';
2
2
  import { HTMLAttributes, ReactElement, ReactNode } from 'react';
3
- export declare function Carousel({ className, spacing, infinite, autoplay, autoplayInterval: autoplayIntervalRaw, disableClipping, renderIndicator, renderNavButton, renderPlayButton, onPageDrag, onPageChange, children }: Carousel.Props): import("react/jsx-runtime").JSX.Element;
3
+ export declare function Carousel({ className, spacing: spacingRaw, infinite, autoplay, autoplayInterval: autoplayIntervalRaw, disableClipping, renderIndicator, renderNavButton, renderPlayButton, onPageDrag, onPageChange, children }: Carousel.Props): import("react/jsx-runtime").JSX.Element;
4
4
  export declare namespace Carousel {
5
5
  export type State = 'initializing' | 'disabled' | 'ready' | 'dragging' | 'animating';
6
6
  export type Props = {
@@ -14,7 +14,7 @@ const rxjs_1 = require("rxjs");
14
14
  const app_1 = require("../app");
15
15
  const hooks_1 = require("../hooks");
16
16
  // component
17
- function Carousel({ className, spacing = 0, infinite = false, autoplay = false, autoplayInterval: autoplayIntervalRaw, disableClipping = false, renderIndicator, renderNavButton, renderPlayButton, onPageDrag = funnel_core_1.Fn.NoOp, onPageChange = funnel_core_1.Fn.NoOp, children = [] }) {
17
+ function Carousel({ className, spacing: spacingRaw, infinite = false, autoplay = false, autoplayInterval: autoplayIntervalRaw, disableClipping = false, renderIndicator, renderNavButton, renderPlayButton, onPageDrag = funnel_core_1.Fn.NoOp, onPageChange = funnel_core_1.Fn.NoOp, children = [] }) {
18
18
  var _a;
19
19
  // bind props + state + hooks
20
20
  const [state, setState] = (0, react_2.useState)('initializing');
@@ -37,18 +37,21 @@ function Carousel({ className, spacing = 0, infinite = false, autoplay = false,
37
37
  const playButtonFocused = !!playButton && keyboardFocusElement === playButton;
38
38
  const childCount = children.length;
39
39
  const gap = (0, react_2.useMemo)(() => {
40
+ // zero if no container
40
41
  if (!container) {
41
- return;
42
+ return 0;
42
43
  }
44
+ // get gap pixel value from css variable
43
45
  const rawValue = getComputedStyle(container).getPropertyValue('--nd-carousel-gap');
44
46
  if (rawValue.endsWith('px')) {
45
47
  return Number.parseInt(rawValue.substring(0, rawValue.length - 2));
46
48
  }
49
+ // otherwise zero
47
50
  else {
48
- return undefined;
51
+ return 0;
49
52
  }
50
53
  }, [container]);
51
- console.debug('>>> carousel', gap);
54
+ const spacing = spacingRaw !== null && spacingRaw !== void 0 ? spacingRaw : (gap / 2);
52
55
  const appConfig = (0, app_1.useAppConfig)();
53
56
  const autoplayInterval = (0, react_2.useMemo)(() => { var _a; return funnel_core_1.Duration.toMilliseconds((_a = autoplayIntervalRaw !== null && autoplayIntervalRaw !== void 0 ? autoplayIntervalRaw : appConfig.ui.carouselInterval) !== null && _a !== void 0 ? _a : '1s'); }, [autoplayIntervalRaw, appConfig]);
54
57
  const reduceMotion = (0, react_1.useReducedMotion)();
@@ -144,10 +144,11 @@ function renderLayout({ renderPanel, layout }) {
144
144
  const { root } = layout;
145
145
  const { items } = root;
146
146
  const siblingCount = items.length;
147
- return ((0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)('nd-Block-root', getContainerClasses(root)), children: items.map((item, index) => (0, jsx_runtime_1.jsx)(react_1.Fragment, { children: renderItem({ renderPanel, parent: root.type, item, siblingCount }) }, `${item.type}.${index}`)) }));
147
+ return ((0, jsx_runtime_1.jsx)("div", { className: "nd-Block-rootContainerWrap", children: (0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)('nd-Block-rootContainer', getContainerClasses(root)), children: items.map((item, index) => (0, jsx_runtime_1.jsx)(react_1.Fragment, { children: renderItem({ renderPanel, parent: root.type, item, siblingCount }) }, `${item.type}.${index}`)) }) }));
148
148
  }
149
- function getContainerClasses({ type, alignX, alignY, items }) {
149
+ function getContainerClasses(container) {
150
150
  var _a;
151
+ const { type, alignX, alignY, items } = container;
151
152
  const itemCount = (_a = items.length) !== null && _a !== void 0 ? _a : 0;
152
153
  return (0, classnames_1.default)({
153
154
  'nd-Block-row': type === 'row',
@@ -26,6 +26,7 @@ export declare namespace RelatedPages {
26
26
  slotVariation: import("..").SlotVariation.Schema;
27
27
  } & Record<"messageTextAlign", Schema.EnumField<Schema.EnumField.Options<import("..").TextAlignment>>> & Record<"messageWidth", Schema.EnumField<Schema.EnumField.Options<import("..").ItemSize>>> & Record<"messageHorizontalAlign", Schema.EnumField<Schema.EnumField.Options<import("..").ItemAlignment>>> & Record<"messageVerticalAlign", Schema.EnumField<Schema.EnumField.Options<import("..").ItemAlignment>>> & {
28
28
  contentAlign: import("..").ItemAlignment.Vertical.Schema;
29
+ contentSplit: import("..").RowRatio.Schema;
29
30
  } & Schema.Block.Config) | ({
30
31
  readonly theme: Schema.EnumField<Readonly<import("@nascentdigital/funnel-core").BlockThemes.Options>>;
31
32
  } & {
@@ -40,6 +41,7 @@ export declare namespace RelatedPages {
40
41
  slotVariation: import("..").SlotVariation.Schema;
41
42
  } & Record<"messageTextAlign", Schema.EnumField<Schema.EnumField.Options<import("..").TextAlignment>>> & Record<"messageWidth", Schema.EnumField<Schema.EnumField.Options<import("..").ItemSize>>> & Record<"messageHorizontalAlign", Schema.EnumField<Schema.EnumField.Options<import("..").ItemAlignment>>> & Record<"messageVerticalAlign", Schema.EnumField<Schema.EnumField.Options<import("..").ItemAlignment>>> & Record<`${any}Layout`, Schema.EnumField<Schema.EnumField.Options<keyof import("..").ListPanelLayout.Configs>>> & Record<`${any}Width`, Schema.EnumField<Schema.EnumField.Options<import("..").ItemSize>>> & Record<`${any}HorizontalAlign`, Schema.EnumField<Schema.EnumField.Options<import("..").ItemAlignment>>> & Record<`${any}VerticalAlign`, Schema.EnumField<Schema.EnumField.Options<import("..").ItemAlignment>>> & {
42
43
  contentAlign: import("..").ItemAlignment.Vertical.Schema;
44
+ contentSplit: import("..").RowRatio.Schema;
43
45
  } & Schema.Block.Config)>;
44
46
  namespace schema {
45
47
  type Args = {
@@ -0,0 +1,51 @@
1
+ import { Schema as SchemaCore } from '@nascentdigital/funnel-core';
2
+ import { Visual } from './Visual';
3
+ export declare function Media({ className, media, ...props }: Media.Props): import("react/jsx-runtime").JSX.Element | null;
4
+ export declare namespace Media {
5
+ namespace Image {
6
+ const schema: SchemaCore.Collection<{
7
+ image: SchemaCore.AssetField<SchemaCore.AssetField.LinkedValue.Image>;
8
+ mobileImage: SchemaCore.Optional<SchemaCore.AssetField<SchemaCore.AssetField.LinkedValue.Image>>;
9
+ }>;
10
+ type Schema = typeof schema;
11
+ type Value = SchemaCore.Collection.LinkedData<Schema>;
12
+ }
13
+ namespace Video {
14
+ const schema: SchemaCore.Collection<{
15
+ video: SchemaCore.AssetField<SchemaCore.AssetField.LinkedValue.Video>;
16
+ cover: SchemaCore.Optional<SchemaCore.AssetField<SchemaCore.AssetField.LinkedValue.Image>>;
17
+ }>;
18
+ type Schema = typeof schema;
19
+ type Value = SchemaCore.Collection.LinkedData<Schema>;
20
+ }
21
+ namespace StreamingVideo {
22
+ const schema: SchemaCore.Collection<{
23
+ video: SchemaCore.EmbeddedVideoField;
24
+ cover: SchemaCore.Optional<SchemaCore.AssetField<SchemaCore.AssetField.LinkedValue.Image>>;
25
+ }>;
26
+ type Schema = typeof schema;
27
+ type Value = SchemaCore.Collection.LinkedData<Schema>;
28
+ }
29
+ const schema: SchemaCore.CollectionField<SchemaCore.Collection<{
30
+ image: SchemaCore.AssetField<SchemaCore.AssetField.LinkedValue.Image>;
31
+ mobileImage: SchemaCore.Optional<SchemaCore.AssetField<SchemaCore.AssetField.LinkedValue.Image>>;
32
+ }> | SchemaCore.Collection<{
33
+ video: SchemaCore.AssetField<SchemaCore.AssetField.LinkedValue.Video>;
34
+ cover: SchemaCore.Optional<SchemaCore.AssetField<SchemaCore.AssetField.LinkedValue.Image>>;
35
+ }> | SchemaCore.Collection<{
36
+ video: SchemaCore.EmbeddedVideoField;
37
+ cover: SchemaCore.Optional<SchemaCore.AssetField<SchemaCore.AssetField.LinkedValue.Image>>;
38
+ }>>;
39
+ type Schema = typeof schema;
40
+ type Value = SchemaCore.Field.LinkedValue<Schema>;
41
+ namespace Value {
42
+ function isImage(value: Value): value is Image.Value;
43
+ function isVideo(value: Value): value is Video.Value;
44
+ function isStreamingVideo(value: Value): value is StreamingVideo.Value;
45
+ }
46
+ type Props = {
47
+ className?: string;
48
+ media?: Value;
49
+ loading?: Visual.Loading;
50
+ };
51
+ }
@@ -0,0 +1,147 @@
1
+ "use strict";
2
+ var __rest = (this && this.__rest) || function (s, e) {
3
+ var t = {};
4
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
5
+ t[p] = s[p];
6
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
7
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
8
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
9
+ t[p[i]] = s[p[i]];
10
+ }
11
+ return t;
12
+ };
13
+ var __importDefault = (this && this.__importDefault) || function (mod) {
14
+ return (mod && mod.__esModule) ? mod : { "default": mod };
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.Media = Media;
18
+ const jsx_runtime_1 = require("react/jsx-runtime");
19
+ const funnel_core_1 = require("@nascentdigital/funnel-core");
20
+ const classnames_1 = __importDefault(require("classnames"));
21
+ const refs_1 = require("../../client/refs");
22
+ const Visual_1 = require("./Visual");
23
+ // component
24
+ function Media(_a) {
25
+ var { className, media } = _a, props = __rest(_a, ["className", "media"]);
26
+ // skip if there's no media
27
+ if (!media) {
28
+ return null;
29
+ }
30
+ // or render image
31
+ let mediaClassName = undefined;
32
+ let content;
33
+ if (Media.Value.isImage(media)) {
34
+ mediaClassName = 'nd-Media-image';
35
+ content = renderImage(Object.assign({ media }, props));
36
+ }
37
+ // or render video
38
+ else if (Media.Value.isVideo(media)) {
39
+ mediaClassName = 'nd-Media-video';
40
+ content = renderVideo(Object.assign({ media }, props));
41
+ }
42
+ // or render streaming video
43
+ else if (Media.Value.isStreamingVideo(media)) {
44
+ mediaClassName = 'nd-Media-streamingVideo';
45
+ content = renderStreamingVideo(Object.assign({ media }, props));
46
+ }
47
+ // or indicate error
48
+ else {
49
+ content = null;
50
+ }
51
+ // render
52
+ return ((0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)('nd-Media', mediaClassName, className), children: content }));
53
+ }
54
+ // extension
55
+ (function (Media) {
56
+ // media types
57
+ let Image;
58
+ (function (Image) {
59
+ // schema
60
+ Image.schema = funnel_core_1.Schema.Collection.create({
61
+ type: '_nd-Media-image',
62
+ name: 'Image',
63
+ description: 'Image content for your website',
64
+ version: 1,
65
+ fields: {
66
+ image: funnel_core_1.Schema.Field.image({ name: 'Primary' }),
67
+ mobileImage: funnel_core_1.Schema.Field.image({ name: 'Mobile Optimized' }).optional()
68
+ }
69
+ });
70
+ })(Image = Media.Image || (Media.Image = {}));
71
+ let Video;
72
+ (function (Video) {
73
+ // schema
74
+ Video.schema = funnel_core_1.Schema.Collection.create({
75
+ type: '_nd-Media-video',
76
+ name: 'Background Video',
77
+ description: 'Small, decorative background video content',
78
+ version: 1,
79
+ fields: {
80
+ video: funnel_core_1.Schema.Field.video({ name: 'Video' }),
81
+ cover: funnel_core_1.Schema.Field.image({ name: 'Cover' }).optional()
82
+ }
83
+ });
84
+ })(Video = Media.Video || (Media.Video = {}));
85
+ let StreamingVideo;
86
+ (function (StreamingVideo) {
87
+ // schema
88
+ StreamingVideo.schema = funnel_core_1.Schema.Collection.create({
89
+ type: '_nd-Media-streamingVideo',
90
+ name: 'Remote Video',
91
+ description: 'Remove streaming video content (Youtube and Vimeo)',
92
+ version: 1,
93
+ fields: {
94
+ video: funnel_core_1.Schema.Field.embeddedVideo({ name: 'Video' }),
95
+ cover: funnel_core_1.Schema.Field.image({ name: 'Cover' }).optional()
96
+ }
97
+ });
98
+ })(StreamingVideo = Media.StreamingVideo || (Media.StreamingVideo = {}));
99
+ // schema
100
+ Media.schema = funnel_core_1.Schema.Field.collection({
101
+ name: 'Media',
102
+ description: 'Image, video, or streaming video content',
103
+ hint: 'Add and configure a local media file or connect to a remote straming video',
104
+ collections: [Image.schema, Video.schema, StreamingVideo.schema]
105
+ });
106
+ let Value;
107
+ (function (Value) {
108
+ // helpers
109
+ function isImage(value) {
110
+ return value.type === Image.schema.type;
111
+ }
112
+ Value.isImage = isImage;
113
+ function isVideo(value) {
114
+ return value.type === Video.schema.type;
115
+ }
116
+ Value.isVideo = isVideo;
117
+ function isStreamingVideo(value) {
118
+ return value.type === StreamingVideo.schema.type;
119
+ }
120
+ Value.isStreamingVideo = isStreamingVideo;
121
+ })(Value = Media.Value || (Media.Value = {}));
122
+ })(Media || (exports.Media = Media = {}));
123
+ function renderImage({ media, loading }) {
124
+ // bind props
125
+ const { image: imageRaw, mobileImage: mobileImageRaw } = media.fields;
126
+ const image = imageRaw === null || imageRaw === void 0 ? void 0 : imageRaw.value;
127
+ const mobileImage = mobileImageRaw === null || mobileImageRaw === void 0 ? void 0 : mobileImageRaw.value;
128
+ // render
129
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(Visual_1.Visual, { className: "nd-Media-image-desktop", visual: image, loading: loading }), mobileImage &&
130
+ (0, jsx_runtime_1.jsx)(Visual_1.Visual, { className: "nd-Media-image-mobile", visual: mobileImage, loading: loading })] }));
131
+ }
132
+ function renderVideo({ media, loading }) {
133
+ // bind props
134
+ const { video: videoRaw, cover: coverRaw } = media.fields;
135
+ const video = videoRaw === null || videoRaw === void 0 ? void 0 : videoRaw.value;
136
+ const cover = coverRaw === null || coverRaw === void 0 ? void 0 : coverRaw.value;
137
+ // render
138
+ return ((0, jsx_runtime_1.jsx)(Visual_1.Visual, { className: "nd-Media-video-player", visual: video, loading: loading, cover: cover }));
139
+ }
140
+ function renderStreamingVideo({ media, loading }) {
141
+ // bind props
142
+ const { video: videoRaw, cover: coverRaw } = media.fields;
143
+ const video = videoRaw === null || videoRaw === void 0 ? void 0 : videoRaw.value;
144
+ const cover = coverRaw === null || coverRaw === void 0 ? void 0 : coverRaw.value;
145
+ // render
146
+ return ((0, jsx_runtime_1.jsx)(refs_1.EmbeddedVideo, { className: "nd-Media-streamingVideo-player", video: video }));
147
+ }
@@ -1,10 +1,11 @@
1
1
  import { Schema } from '@nascentdigital/funnel-core';
2
2
  import { HTMLAttributes } from 'react';
3
- export declare function Visual({ className, visual, loading, ...props }: Visual.Props): import("react/jsx-runtime").JSX.Element | null;
3
+ export declare function Visual({ className, visual, cover, loading, ...props }: Visual.Props): import("react/jsx-runtime").JSX.Element | null;
4
4
  export declare namespace Visual {
5
5
  const schema: Schema.AssetField<Schema.AssetField.LinkedValue.Visual>;
6
6
  type Props = Omit<HTMLAttributes<HTMLImageElement> & HTMLAttributes<HTMLVideoElement>, 'children'> & {
7
7
  visual?: Model;
8
+ cover?: Schema.AssetField.LinkedValue.Image;
8
9
  loading?: Loading;
9
10
  };
10
11
  type Model = Schema.Field.LinkedValue<typeof schema>;
@@ -22,7 +22,7 @@ const image_1 = __importDefault(require("next/image"));
22
22
  const refs_1 = require("../../client/refs");
23
23
  // component
24
24
  function Visual(_a) {
25
- var { className, visual, loading = 'lazy' } = _a, props = __rest(_a, ["className", "visual", "loading"]);
25
+ var { className, visual, cover, loading = 'lazy' } = _a, props = __rest(_a, ["className", "visual", "cover", "loading"]);
26
26
  // skip if not set
27
27
  if (!visual) {
28
28
  return null;
@@ -44,14 +44,14 @@ function Visual(_a) {
44
44
  else if (loading === 'eager') {
45
45
  const { type, url, metadata: { crop = 'center', dimensions } = {} } = visual !== null && visual !== void 0 ? visual : {};
46
46
  const { width, height } = dimensions !== null && dimensions !== void 0 ? dimensions : {};
47
- return ((0, jsx_runtime_1.jsx)("video", Object.assign({}, props, { className: (0, classnames_1.default)(className, 'nd-Visual nd-Visual-video'), autoPlay: true, muted: true, loop: true, playsInline: true, style: {
47
+ return ((0, jsx_runtime_1.jsx)("video", Object.assign({}, props, { className: (0, classnames_1.default)(className, 'nd-Visual nd-Visual-video'), autoPlay: true, muted: true, loop: true, playsInline: true, poster: cover === null || cover === void 0 ? void 0 : cover.url, style: {
48
48
  '--_nd-visual-native-width': width ? `${width}` : '1',
49
49
  '--_nd-visual-native-height': height ? `${height}` : '1'
50
50
  }, children: (0, jsx_runtime_1.jsx)("source", { src: url, type: type }) })));
51
51
  }
52
52
  // or render image
53
53
  else {
54
- return ((0, jsx_runtime_1.jsx)(refs_1.LazyVideo, Object.assign({}, props, { className: (0, classnames_1.default)(className, 'nd-Visual nd-Visual-video'), video: visual })));
54
+ return ((0, jsx_runtime_1.jsx)(refs_1.LazyVideo, Object.assign({}, props, { className: (0, classnames_1.default)(className, 'nd-Visual nd-Visual-video'), video: visual, poster: cover === null || cover === void 0 ? void 0 : cover.url })));
55
55
  }
56
56
  }
57
57
  // extension
@@ -5,6 +5,7 @@ export * from './FreeFormContent';
5
5
  export * from './Headline';
6
6
  export * from './Icon';
7
7
  export * from './Link';
8
+ export * from './Media';
8
9
  export * from './Quote';
9
10
  export * from './RichText';
10
11
  export * from './Title';
@@ -21,6 +21,7 @@ __exportStar(require("./FreeFormContent"), exports);
21
21
  __exportStar(require("./Headline"), exports);
22
22
  __exportStar(require("./Icon"), exports);
23
23
  __exportStar(require("./Link"), exports);
24
+ __exportStar(require("./Media"), exports);
24
25
  __exportStar(require("./Quote"), exports);
25
26
  __exportStar(require("./RichText"), exports);
26
27
  __exportStar(require("./Title"), exports);
@@ -1,5 +1,5 @@
1
1
  import { BlockLayout, Schema } from '@nascentdigital/funnel-core';
2
- import { BlockConfig, ItemAlignment, PanelLayout, SlotVariation } from '../schema';
2
+ import { BlockConfig, ItemAlignment, PanelLayout, RowRatio, SlotVariation } from '../schema';
3
3
  import { ListPanel } from './ListPanel';
4
4
  import { MessagePanel } from './MessagePanel';
5
5
  import { VisualPanel } from './VisualPanel';
@@ -67,10 +67,13 @@ export declare namespace BlockPanel {
67
67
  slotVariation: SlotVariation.Schema;
68
68
  } & (TMessageKey extends string ? MessagePanel.Config.Entries<TMessageKey> : {}) & (TVisualKey extends Schema.Fields.AssetFields.Keys<TFields> ? VisualPanel.Config.Entries<TVisualKey> : {}) & (TListKey extends Schema.Fields.ListFields.Keys<TFields> ? ListPanel.Config.Entries<TListKey> : {}) & (TMessageKey extends string ? TVisualKey extends Schema.Fields.AssetFields.Keys<TFields> ? ({
69
69
  contentAlign: ItemAlignment.Vertical.Schema;
70
+ contentSplit: RowRatio.Schema;
70
71
  }) : TListKey extends Schema.Fields.ListFields.Keys<TFields> ? ({
71
72
  contentAlign: ItemAlignment.Vertical.Schema;
73
+ contentSplit: RowRatio.Schema;
72
74
  }) : {} : TVisualKey extends Schema.Fields.AssetFields.Keys<TFields> ? TListKey extends Schema.Fields.ListFields.Keys<TFields> ? ({
73
75
  contentAlign: ItemAlignment.Vertical.Schema;
76
+ contentSplit: RowRatio.Schema;
74
77
  }) : {} : {})) & TConfigExtended;
75
78
  }
76
79
  function getConfigSchema<TFields extends Schema.Fields, TMessageKey extends string | undefined = undefined, TVisualKey extends Schema.Fields.AssetFields.Keys<TFields> | undefined = undefined, TListKey extends Schema.Fields.ListFields.Keys<TFields> | undefined = undefined, TConfigExtended extends Schema.Block.Config = Schema.Block.Config>({ extend, messageKey: messageKeyRaw, visualKey: visualKeyRaw, listKey: listKeyRaw }: GetConfigSchema.Args<TFields, TMessageKey, TVisualKey, TListKey, TConfigExtended>): GetConfigSchema.Result<TFields, TMessageKey, TVisualKey, TListKey, TConfigExtended>;
@@ -329,16 +329,17 @@ var BlockPanel;
329
329
  .Horizontal.schema.rename(`${visualLabel} ${schema_1.ItemAlignment.Horizontal.schema.name}`)
330
330
  .optional();
331
331
  }
332
- // add content alignment if there are more than 2 panels
332
+ // add content alignment/split if there are more than 2 panels
333
333
  if (panelCount > 1) {
334
334
  configSchema['contentAlign'] = schema_1.ItemAlignment.Vertical.schema.rename('Content Alignment').optional();
335
+ configSchema['contentSplit'] = schema_1.RowRatio.schema.rename('Content Split').optional();
335
336
  }
336
337
  // return
337
338
  return configSchema;
338
339
  }
339
340
  BlockPanel.getConfigSchema = getConfigSchema;
340
341
  function getConfig({ args, messageFieldKeys, messageKey, visualKey, listKey }) {
341
- var _a, _b, _c, _d, _e, _f, _g, _h;
342
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
342
343
  // throw if there are not enough panels
343
344
  const panelCount = [messageKey, visualKey, listKey].filter(funnel_core_1.Value.isDefined).length;
344
345
  if (panelCount === 0) {
@@ -418,7 +419,7 @@ var BlockPanel;
418
419
  flexDirection: flexDirections.L
419
420
  });
420
421
  }
421
- // create new schema (drop content alignment if it's not applicable)
422
+ // create new schema
422
423
  const updatedConfigSchema = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, Object.entries(configSchema)
423
424
  .reduce((configSchema, [key, fieldSchema]) => {
424
425
  // add the config back if it's not in the panel config keys
@@ -428,17 +429,21 @@ var BlockPanel;
428
429
  // keep reducing
429
430
  return configSchema;
430
431
  }, {})), messageConfig === null || messageConfig === void 0 ? void 0 : messageConfig.configSchema), visualConfig === null || visualConfig === void 0 ? void 0 : visualConfig.configSchema), listConfig === null || listConfig === void 0 ? void 0 : listConfig.configSchema), { layout: layoutSchema, slotVariation: slotVariationSchema });
432
+ // drop content alignment if it's not applicable
431
433
  if (!BlockPanel.Slots.contentAlignmentExists(layout)) {
432
434
  delete updatedConfigSchema.contentAlign;
433
435
  }
436
+ // drop layout/content split if not applicable
434
437
  if (panelCount < 2) {
435
438
  delete updatedConfigSchema.layout;
439
+ delete updatedConfigSchema.contentSplit;
436
440
  }
437
441
  // create default config
438
- const defaultConfig = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, config), { theme: funnel_core_1.Schema.EnumField.Value.toData('default'), contentAlign: funnel_core_1.Schema.EnumField.Value.toData('start') }), messageConfig === null || messageConfig === void 0 ? void 0 : messageConfig.defaultConfig), visualConfig === null || visualConfig === void 0 ? void 0 : visualConfig.defaultConfig), listConfig === null || listConfig === void 0 ? void 0 : listConfig.defaultConfig), { layout: funnel_core_1.Schema.EnumField.Value.toData((_e = layoutSchema.defaultOption) !== null && _e !== void 0 ? _e : 'solo'), slotVariation: funnel_core_1.Schema.EnumField.Value.toData((_f = slotVariationSchema.defaultOption) !== null && _f !== void 0 ? _f : 'v1') });
442
+ const defaultConfig = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, config), { theme: funnel_core_1.Schema.EnumField.Value.toData('default'), contentAlign: funnel_core_1.Schema.EnumField.Value.toData('start'), contentSplit: funnel_core_1.Schema.EnumField.Value.toData('1/1') }), messageConfig === null || messageConfig === void 0 ? void 0 : messageConfig.defaultConfig), visualConfig === null || visualConfig === void 0 ? void 0 : visualConfig.defaultConfig), listConfig === null || listConfig === void 0 ? void 0 : listConfig.defaultConfig), { layout: funnel_core_1.Schema.EnumField.Value.toData((_e = layoutSchema.defaultOption) !== null && _e !== void 0 ? _e : 'solo'), slotVariation: funnel_core_1.Schema.EnumField.Value.toData((_f = slotVariationSchema.defaultOption) !== null && _f !== void 0 ? _f : 'v1') });
439
443
  const contentAlign = ((_h = (_g = config.contentAlign) === null || _g === void 0 ? void 0 : _g.value) !== null && _h !== void 0 ? _h : 'start');
444
+ const contentSplit = ((_k = (_j = config.contentSplit) === null || _j === void 0 ? void 0 : _j.value) !== null && _k !== void 0 ? _k : '1/1');
440
445
  // create new config
441
- const updatedConfig = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, config), messageConfig === null || messageConfig === void 0 ? void 0 : messageConfig.config), visualConfig === null || visualConfig === void 0 ? void 0 : visualConfig.config), listConfig === null || listConfig === void 0 ? void 0 : listConfig.config), { layout: funnel_core_1.Schema.EnumField.Value.toData(layout), slotVariation: funnel_core_1.Schema.EnumField.Value.toData(slotVariation), contentAlign: funnel_core_1.Schema.EnumField.Value.toData(contentAlign) });
446
+ const updatedConfig = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, config), messageConfig === null || messageConfig === void 0 ? void 0 : messageConfig.config), visualConfig === null || visualConfig === void 0 ? void 0 : visualConfig.config), listConfig === null || listConfig === void 0 ? void 0 : listConfig.config), { layout: funnel_core_1.Schema.EnumField.Value.toData(layout), slotVariation: funnel_core_1.Schema.EnumField.Value.toData(slotVariation), contentAlign: funnel_core_1.Schema.EnumField.Value.toData(contentAlign), contentSplit: funnel_core_1.Schema.EnumField.Value.toData(contentSplit) });
442
447
  // return config
443
448
  return {
444
449
  updatedConfigSchema: updatedConfigSchema,
@@ -448,7 +453,7 @@ var BlockPanel;
448
453
  }
449
454
  BlockPanel.getConfig = getConfig;
450
455
  function getLayout({ args, messageFieldKeys, messageKey, visualKey, listKey }) {
451
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3;
456
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5;
452
457
  // throw if there are not enough panels
453
458
  const panelCount = [messageKey, visualKey, listKey].filter(funnel_core_1.Value.isDefined).length;
454
459
  if (panelCount === 0) {
@@ -456,7 +461,6 @@ var BlockPanel;
456
461
  }
457
462
  // resolve props
458
463
  const config = args.config;
459
- const fields = args.fields;
460
464
  const messageKeys = messageKey
461
465
  ? MessagePanel_1.MessagePanel.Config.getKeys(messageKey)
462
466
  : {};
@@ -481,26 +485,27 @@ var BlockPanel;
481
485
  layout,
482
486
  variation: slotVariation
483
487
  });
484
- // compute content alignment config
488
+ // compute content alignment/split config
485
489
  const contentAlign = (_f = (_e = config.contentAlign) === null || _e === void 0 ? void 0 : _e.value) !== null && _f !== void 0 ? _f : 'start';
490
+ const contentSplit = ((_h = (_g = config.contentSplit) === null || _g === void 0 ? void 0 : _g.value) !== null && _h !== void 0 ? _h : '1/1');
486
491
  // compute message config
487
- const messageWidthRaw = (_g = config[messageKeys.width]) === null || _g === void 0 ? void 0 : _g.value;
492
+ const messageWidthRaw = (_j = config[messageKeys.width]) === null || _j === void 0 ? void 0 : _j.value;
488
493
  const isMessageFullBleed = messageWidthRaw === 'fullBleed';
489
- const messageWidth = isMessageFullBleed ? 'full' : (_j = (_h = config[messageKeys.width]) === null || _h === void 0 ? void 0 : _h.value) !== null && _j !== void 0 ? _j : 'full';
490
- const messageTextAlign = (_l = (_k = config[messageKeys.textAlign]) === null || _k === void 0 ? void 0 : _k.value) !== null && _l !== void 0 ? _l : 'left';
491
- const messageHorizontalAlign = (_o = (_m = config[messageKeys.horizontalAlign]) === null || _m === void 0 ? void 0 : _m.value) !== null && _o !== void 0 ? _o : 'start';
492
- const messageVerticalAlign = (_q = (_p = config[messageKeys.verticalAlign]) === null || _p === void 0 ? void 0 : _p.value) !== null && _q !== void 0 ? _q : 'start';
494
+ const messageWidth = isMessageFullBleed ? 'full' : (_l = (_k = config[messageKeys.width]) === null || _k === void 0 ? void 0 : _k.value) !== null && _l !== void 0 ? _l : 'full';
495
+ const messageTextAlign = (_o = (_m = config[messageKeys.textAlign]) === null || _m === void 0 ? void 0 : _m.value) !== null && _o !== void 0 ? _o : 'left';
496
+ const messageHorizontalAlign = (_q = (_p = config[messageKeys.horizontalAlign]) === null || _p === void 0 ? void 0 : _p.value) !== null && _q !== void 0 ? _q : 'start';
497
+ const messageVerticalAlign = (_s = (_r = config[messageKeys.verticalAlign]) === null || _r === void 0 ? void 0 : _r.value) !== null && _s !== void 0 ? _s : 'start';
493
498
  // compute visual config
494
- const visualAspect = (_s = (_r = config[visualKeys.aspect]) === null || _r === void 0 ? void 0 : _r.value) !== null && _s !== void 0 ? _s : 'auto';
495
- const visualWidth = ((_u = (_t = config[visualKeys.width]) === null || _t === void 0 ? void 0 : _t.value) !== null && _u !== void 0 ? _u : 'full');
496
- const visualHorizontalAlign = (_w = (_v = config[visualKeys.horizontalAlign]) === null || _v === void 0 ? void 0 : _v.value) !== null && _w !== void 0 ? _w : 'start';
499
+ const visualAspect = (_u = (_t = config[visualKeys.aspect]) === null || _t === void 0 ? void 0 : _t.value) !== null && _u !== void 0 ? _u : 'auto';
500
+ const visualWidth = ((_w = (_v = config[visualKeys.width]) === null || _v === void 0 ? void 0 : _v.value) !== null && _w !== void 0 ? _w : 'full');
501
+ const visualHorizontalAlign = (_y = (_x = config[visualKeys.horizontalAlign]) === null || _x === void 0 ? void 0 : _x.value) !== null && _y !== void 0 ? _y : 'start';
497
502
  const isVisualFullBleed = visualWidth === 'fullBleed';
498
503
  // compute list config
499
- const listWidthRaw = (_x = config[listKeys.width]) === null || _x === void 0 ? void 0 : _x.value;
504
+ const listWidthRaw = (_z = config[listKeys.width]) === null || _z === void 0 ? void 0 : _z.value;
500
505
  const isListFullBleed = listWidthRaw === 'fullBleed';
501
- const listWidth = isListFullBleed ? 'full' : (_z = (_y = config[listKeys.width]) === null || _y === void 0 ? void 0 : _y.value) !== null && _z !== void 0 ? _z : 'full';
502
- const listHorizontalAlign = (_1 = (_0 = config[listKeys.horizontalAlign]) === null || _0 === void 0 ? void 0 : _0.value) !== null && _1 !== void 0 ? _1 : 'start';
503
- const listVerticalAlign = (_3 = (_2 = config[listKeys.verticalAlign]) === null || _2 === void 0 ? void 0 : _2.value) !== null && _3 !== void 0 ? _3 : 'start';
506
+ const listWidth = isListFullBleed ? 'full' : (_1 = (_0 = config[listKeys.width]) === null || _0 === void 0 ? void 0 : _0.value) !== null && _1 !== void 0 ? _1 : 'full';
507
+ const listHorizontalAlign = (_3 = (_2 = config[listKeys.horizontalAlign]) === null || _2 === void 0 ? void 0 : _2.value) !== null && _3 !== void 0 ? _3 : 'start';
508
+ const listVerticalAlign = (_5 = (_4 = config[listKeys.verticalAlign]) === null || _4 === void 0 ? void 0 : _4.value) !== null && _5 !== void 0 ? _5 : 'start';
504
509
  // create visual if we have one
505
510
  let visualSlot = undefined;
506
511
  if (items.includes('V') || schema_1.PanelLayout.isNested(layout)) {
@@ -580,7 +585,7 @@ var BlockPanel;
580
585
  tightDesktop="${tightDesktop}"
581
586
  tightMobile="${tightMobile}"
582
587
  >
583
- <row alignY="${contentAlign}">
588
+ <row alignY="${contentAlign}" ratioDesktop="${contentSplit}">
584
589
  ${slots[0]}
585
590
  ${slots[1]}
586
591
  </row>
@@ -618,7 +623,7 @@ var BlockPanel;
618
623
  <block xmlns="nd:block" name="Nested: Horizontal">
619
624
  <stack>
620
625
  ${visualSlot}
621
- <row alignY="${contentAlign}">
626
+ <row alignY="${contentAlign}" ratioDesktop="${contentSplit}">
622
627
  ${slots[0]}
623
628
  ${slots[1]}
624
629
  </row>
@@ -658,7 +663,7 @@ var BlockPanel;
658
663
  // language=XML
659
664
  blockLayout = `
660
665
  <block xmlns="nd:block" name="Nested: Right">
661
- <row alignY="${contentAlign}">
666
+ <row alignY="${contentAlign}" ratioDesktop="${contentSplit}">
662
667
  ${slots[0]}
663
668
  <stack>
664
669
  ${visualSlot}
@@ -686,7 +691,7 @@ var BlockPanel;
686
691
  // language=XML
687
692
  blockLayout = `
688
693
  <block xmlns="nd:block" name="Nested: Left">
689
- <row alignY="${contentAlign}">
694
+ <row alignY="${contentAlign}" ratioDesktop="${contentSplit}">
690
695
  <stack>
691
696
  ${visualSlot}
692
697
  ${slots[0]}
@@ -751,7 +756,7 @@ var BlockPanel;
751
756
  >
752
757
  <col>
753
758
  ${slots[0]}
754
- <row alignY="${contentAlign}">
759
+ <row alignY="${contentAlign}" ratioDesktop="${contentSplit}">
755
760
  ${slots[1]}
756
761
  ${slots[2]}
757
762
  </row>
@@ -786,7 +791,7 @@ var BlockPanel;
786
791
  tightDesktop="${tightDesktop}"
787
792
  tightMobile="${tightMobile}"
788
793
  >
789
- <row alignY="${contentAlign}">
794
+ <row alignY="${contentAlign}" ratioDesktop="${contentSplit}">
790
795
  <col>
791
796
  ${slots[0]}
792
797
  ${slots[2]}
@@ -824,7 +829,7 @@ var BlockPanel;
824
829
  tightMobile="${tightMobile}"
825
830
  >
826
831
  <col>
827
- <row alignY="${contentAlign}">
832
+ <row alignY="${contentAlign}" ratioDesktop="${contentSplit}">
828
833
  ${slots[0]}
829
834
  ${slots[1]}
830
835
  </row>
@@ -854,20 +859,20 @@ var BlockPanel;
854
859
  }
855
860
  // language=XML
856
861
  blockLayout = `
857
- <block
858
- xmlns="nd:block"
859
- name="Brick: Left"
860
- tightDesktop="${tightDesktop}"
861
- tightMobile="${tightMobile}"
862
- >
863
- <row alignY="${contentAlign}">
864
- ${slots[0]}
865
- <col>
866
- ${slots[1]}
867
- ${slots[2]}
868
- </col>
869
- </row>
870
- </block>
862
+ <block
863
+ xmlns="nd:block"
864
+ name="Brick: Left"
865
+ tightDesktop="${tightDesktop}"
866
+ tightMobile="${tightMobile}"
867
+ >
868
+ <row alignY="${contentAlign}" ratioDesktop="${contentSplit}">
869
+ ${slots[0]}
870
+ <col>
871
+ ${slots[1]}
872
+ ${slots[2]}
873
+ </col>
874
+ </row>
875
+ </block>
871
876
  `;
872
877
  break;
873
878
  }
@@ -0,0 +1,7 @@
1
+ import { Schema } from '@nascentdigital/funnel-core';
2
+ export type RowRatio = '3/1' | '2/1' | '3/2' | '1/1' | '2/3' | '1/2' | '1/3';
3
+ export declare namespace RowRatio {
4
+ const options: Schema.EnumField.Options<RowRatio>;
5
+ const schema: Schema.EnumField<Schema.EnumField.Options<RowRatio>>;
6
+ type Schema = typeof schema;
7
+ }
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RowRatio = void 0;
4
+ const funnel_core_1 = require("@nascentdigital/funnel-core");
5
+ // extension
6
+ var RowRatio;
7
+ (function (RowRatio) {
8
+ // schema
9
+ RowRatio.options = {
10
+ '3/1': { name: '3/1' },
11
+ '2/1': { name: '2/1' },
12
+ '3/2': { name: '3/2' },
13
+ '1/1': { name: '1/1' },
14
+ '2/3': { name: '2/3' },
15
+ '1/2': { name: '1/2' },
16
+ '1/3': { name: '1/3' }
17
+ };
18
+ RowRatio.schema = funnel_core_1.Schema.Field.enumeration({
19
+ name: 'Row Ratio',
20
+ semantics: 'dropdown',
21
+ hint: 'Set row ratio',
22
+ description: 'Determines how row spacing is distributed.',
23
+ options: RowRatio.options,
24
+ defaultOption: '1/1'
25
+ });
26
+ })(RowRatio || (exports.RowRatio = RowRatio = {}));
@@ -6,5 +6,6 @@ export * from './ItemPosition';
6
6
  export * from './ItemSize';
7
7
  export * from './ListPanelLayout';
8
8
  export * from './PanelLayout';
9
+ export * from './RowRatio';
9
10
  export * from './SlotVariation';
10
11
  export * from './TextAlignment';
@@ -22,5 +22,6 @@ __exportStar(require("./ItemPosition"), exports);
22
22
  __exportStar(require("./ItemSize"), exports);
23
23
  __exportStar(require("./ListPanelLayout"), exports);
24
24
  __exportStar(require("./PanelLayout"), exports);
25
+ __exportStar(require("./RowRatio"), exports);
25
26
  __exportStar(require("./SlotVariation"), exports);
26
27
  __exportStar(require("./TextAlignment"), exports);
@@ -28,31 +28,71 @@
28
28
  .nd-Block {
29
29
  min-height: var(--nd-block-height-min);
30
30
  }
31
- .nd-Block-root {
32
- }
31
+ .nd-Block-rootContainerWrap {
33
32
 
34
- /* container/fullbleed */
35
- ._nd-Block-containable {
33
+ /* for row (always on) */
34
+ &:has(> .nd-Block-row) {
35
+ @apply container-p;
36
+ }
37
+ > .nd-Block-rootContainer > .nd-Block-row {
38
+ @media screen and (max-width: theme('screens.md')) {
39
+ &:has(.nd-BlockPanel:is(.nd-BlockPanel-fullbleed,.nd-BlockPanel-fullbleed-mobile)) {
40
+ @apply container-p;
41
+ }
42
+ }
43
+ @media screen(md) {
44
+ &:has(.nd-BlockPanel:is(.nd-BlockPanel-fullbleed,.nd-BlockPanel-fullbleed-tablet)) {
45
+ @apply container-p;
46
+ }
47
+ }
48
+ @media screen(lg) {
49
+ &:has(.nd-BlockPanel:is(.nd-BlockPanel-fullbleed,.nd-BlockPanel-fullbleed-desktop)) {
50
+ @apply container-p;
51
+ }
52
+ }
53
+ }
36
54
 
37
- /* container */
38
- &.nd-Block-root > .nd-BlockPanel {
55
+ /* for column/stack (apply container to panels if not fullbleed) */
56
+ &:has(> :is(.nd-Block-column, .nd-Block-stack)) {
39
57
  @media screen and (max-width: theme('screens.md')) {
40
- &:not(.nd-BlockPanel-fullbleed):not(.nd-BlockPanel-fullbleed-mobile) {
58
+ &:not(:has(.nd-BlockPanel:is(.nd-BlockPanel-fullbleed,.nd-BlockPanel-fullbleed-mobile))) {
41
59
  @apply container-p;
42
60
  }
61
+ &:has(.nd-BlockPanel:is(.nd-BlockPanel-fullbleed,.nd-BlockPanel-fullbleed-mobile)) {
62
+
63
+ > .nd-Block-rootContainer > *:not(:is(.nd-BlockPanel-fullbleed,.nd-BlockPanel-fullbleed-mobile)):not(:has(.nd-BlockPanel:is(.nd-BlockPanel-fullbleed,.nd-BlockPanel-fullbleed-mobile))) {
64
+ @apply container-p;
65
+ }
66
+ }
43
67
  }
44
68
  @media screen(md) {
45
- &:not(.nd-BlockPanel-fullbleed):not(.nd-BlockPanel-fullbleed-tablet) {
69
+ &:not(:has(.nd-BlockPanel:is(.nd-BlockPanel-fullbleed,.nd-BlockPanel-fullbleed-tablet))) {
46
70
  @apply container-p;
47
71
  }
72
+ &:has(.nd-BlockPanel:is(.nd-BlockPanel-fullbleed,.nd-BlockPanel-fullbleed-tablet)) {
73
+
74
+ > .nd-Block-rootContainer > *:not(:is(.nd-BlockPanel-fullbleed,.nd-BlockPanel-fullbleed-tablet)):not(:has(.nd-BlockPanel:is(.nd-BlockPanel-fullbleed,.nd-BlockPanel-fullbleed-tablet))) {
75
+ @apply container-p;
76
+ }
77
+ }
48
78
  }
49
79
  @media screen(lg) {
50
- &:not(.nd-BlockPanel-fullbleed):not(.nd-BlockPanel-fullbleed-desktop) {
80
+ &:not(:has(.nd-BlockPanel:is(.nd-BlockPanel-fullbleed,.nd-BlockPanel-fullbleed-desktop))) {
51
81
  @apply container-p;
52
82
  }
83
+ &:has(.nd-BlockPanel:is(.nd-BlockPanel-fullbleed,.nd-BlockPanel-fullbleed-desktop)) {
84
+
85
+ > .nd-Block-rootContainer > *:not(:is(.nd-BlockPanel-fullbleed,.nd-BlockPanel-fullbleed-desktop)):not(:has(.nd-BlockPanel:is(.nd-BlockPanel-fullbleed,.nd-BlockPanel-fullbleed-desktop))) {
86
+ @apply container-p;
87
+ }
88
+ }
53
89
  }
54
90
  }
55
91
  }
92
+ .nd-Block-rootContainer {
93
+ }
94
+
95
+ /* container/fullbleed */
56
96
  ._nd-Block-fullbleed-left {
57
97
  margin-left: calc((100dvw - 100cqw) / -2);
58
98
  }
@@ -63,11 +103,11 @@
63
103
 
64
104
  /* row layout */
65
105
  ._nd-Block-row-mobile {
66
- @apply container-p flex flex-col gap-[var(--nd-block-layout-gap-y)];
106
+ @apply flex flex-col gap-[var(--nd-block-layout-gap-y)];
67
107
  container-type: inline-size;
68
108
 
69
109
  /* fullbleed (l1 only) */
70
- &.nd-Block-root > .nd-BlockPanel {
110
+ &.nd-Block-rootContainer > .nd-BlockPanel {
71
111
  &.nd-BlockPanel-fullbleed {
72
112
  @apply _nd-Block-fullbleed-left _nd-Block-fullbleed-right;
73
113
  }
@@ -77,7 +117,7 @@
77
117
  }
78
118
  }
79
119
  ._nd-Block-row-desktop {
80
- @apply container-p grid auto-cols-fr gap-[var(--nd-block-layout-gap-x)];
120
+ @apply grid auto-cols-fr gap-[var(--nd-block-layout-gap-x)];
81
121
  container-type: inline-size;
82
122
 
83
123
  /* row widths */
@@ -105,8 +145,8 @@
105
145
  @apply items-end;
106
146
  }
107
147
 
108
- /* fullbleed (l1 only) */
109
- &.nd-Block-root > .nd-BlockPanel {
148
+ /* fullbleed (l1 OR l2) */
149
+ & > .nd-BlockPanel {
110
150
  &.nd-BlockPanel-fullbleed {
111
151
  &:first-child {
112
152
  @apply _nd-Block-fullbleed-left;
@@ -149,12 +189,12 @@
149
189
  @apply grid grid-cols-1 grid-flow-row gap-[var(--nd-block-layout-gap-y)];
150
190
  }
151
191
  .nd-Block-column {
152
- @apply w-full max-md:_nd-Block-column-mobile md:_nd-Block-column-desktop _nd-Block-containable;
192
+ @apply w-full max-md:_nd-Block-column-mobile md:_nd-Block-column-desktop;
153
193
  }
154
194
 
155
195
  /* column layout */
156
196
  .nd-Block-stack {
157
- @apply stacked _nd-Block-containable;
197
+ @apply stacked;
158
198
 
159
199
  /* z-indexing */
160
200
  > *:nth-child(1) {
@@ -8,7 +8,7 @@
8
8
  @apply flex flex-col justify-center;
9
9
 
10
10
  .nd-YoutubePlayer-thumbnail {
11
- @apply absolute inset-0 z-supersurface;
11
+ @apply absolute inset-0 w-full h-full object-cover z-supersurface;
12
12
  }
13
13
 
14
14
  iframe {
@@ -0,0 +1,37 @@
1
+ @layer components {
2
+
3
+ /* variables */
4
+ :root {
5
+ }
6
+
7
+
8
+ /* base */
9
+ .nd-Media {
10
+ }
11
+
12
+ /* image */
13
+ .nd-Media-image {
14
+ @apply stacked;
15
+
16
+ /* desktop (hide if mobile is enabled) */
17
+ &:has(.nd-Media-image-mobile) > .nd-Media-image-desktop {
18
+ @apply hidden md:block;
19
+ }
20
+
21
+ /* mobile */
22
+ .nd-Media-image-mobile {
23
+ @apply block md:hidden;
24
+ }
25
+ }
26
+
27
+ /* video */
28
+ .nd-Media-video {
29
+ }
30
+
31
+ /* streaming video (youtube/vimeo) */
32
+ .nd-Media-streamingVideo {
33
+ }
34
+ .nd-Media-streamingVideo-player {
35
+ @apply w-full h-full;
36
+ }
37
+ }
@@ -25,4 +25,9 @@
25
25
  object-position: var(--nd-visual-anchor);
26
26
  }
27
27
  }
28
+
29
+ img.nd-Visual-image {
30
+ object-fit: var(--nd-visual-object-fit, cover);
31
+ object-position: var(--nd-visual-anchor);
32
+ }
28
33
  }
@@ -5,6 +5,7 @@
5
5
  @import "./Icon.css";
6
6
  @import "./LazyVideo.css";
7
7
  @import "./Link.css";
8
+ @import "./Media.css";
8
9
  @import "./Quote.css";
9
10
  @import "./RichText.css";
10
11
  @import "./Title.css";
@@ -10,6 +10,7 @@
10
10
  /* aspect ratios */
11
11
  .nd-VisualPanel-aspect-auto {
12
12
  --nd-visual-aspect: theme(aspectRatio.auto);
13
+ --nd-visual-height: auto;
13
14
  }
14
15
  .nd-VisualPanel-aspect-square {
15
16
  --nd-visual-aspect: theme(aspectRatio.square);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@nascentdigital/funnel-ui",
3
3
  "description": "UI components for funnel",
4
- "version": "4.6.0",
4
+ "version": "4.6.7",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/",
7
7
  "access": "restricted"
@@ -69,5 +69,5 @@
69
69
  "react-dom": "^19",
70
70
  "ts-jest": "^29.3.2"
71
71
  },
72
- "gitHead": "7fba18243bc79f94b3bd665db21f37bc7f3afd4c"
72
+ "gitHead": "b17e33b4400391b3984e61225c572f097c4c26c9"
73
73
  }