@obosbbl/grunnmuren-react 3.4.2 → 3.4.4
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.
- package/dist/__stories__/form-validation.stories.cjs +501 -0
- package/dist/__stories__/form-validation.stories.d.cts +11 -0
- package/dist/__stories__/form-validation.stories.d.ts +11 -0
- package/dist/__stories__/form-validation.stories.js +495 -0
- package/dist/__stories__/home.stories.cjs +32 -0
- package/dist/__stories__/home.stories.d.cts +10 -0
- package/dist/__stories__/home.stories.d.ts +10 -0
- package/dist/__stories__/home.stories.js +29 -0
- package/dist/__stories__/icons.stories.cjs +47 -0
- package/dist/__stories__/icons.stories.d.cts +8 -0
- package/dist/__stories__/icons.stories.d.ts +8 -0
- package/dist/__stories__/icons.stories.js +24 -0
- package/dist/__stories__/layout.stories.cjs +599 -0
- package/dist/__stories__/layout.stories.d.cts +10 -0
- package/dist/__stories__/layout.stories.d.ts +10 -0
- package/dist/__stories__/layout.stories.js +594 -0
- package/dist/__stories__/typography.stories.cjs +224 -0
- package/dist/__stories__/typography.stories.d.cts +14 -0
- package/dist/__stories__/typography.stories.d.ts +14 -0
- package/dist/__stories__/typography.stories.js +214 -0
- package/dist/index.d.mts +649 -754
- package/dist/index.mjs +2984 -2315
- package/package.json +12 -12
|
@@ -0,0 +1,599 @@
|
|
|
1
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
2
|
+
|
|
3
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
4
|
+
var grunnmurenIconsReact = require('@obosbbl/grunnmuren-icons-react');
|
|
5
|
+
var cva = require('cva');
|
|
6
|
+
var reactAriaComponents = require('react-aria-components');
|
|
7
|
+
var react = require('react');
|
|
8
|
+
|
|
9
|
+
const HeadingContext = /*#__PURE__*/ react.createContext({});
|
|
10
|
+
const headingVariants = cva.cva({
|
|
11
|
+
variants: {
|
|
12
|
+
/** The visual text size of the heading */ size: {
|
|
13
|
+
xl: 'heading-xl',
|
|
14
|
+
l: 'heading-l',
|
|
15
|
+
m: 'heading-m',
|
|
16
|
+
s: 'heading-s',
|
|
17
|
+
xs: 'heading-xs'
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
const Heading = ({ ref = null, ...props })=>{
|
|
22
|
+
[props, ref] = reactAriaComponents.useContextProps(props, ref, HeadingContext);
|
|
23
|
+
const { children, level, size, className, _innerWrapper: innerWrapper, _outerWrapper: outerWrapper, ...restProps } = props;
|
|
24
|
+
const _className = headingVariants({
|
|
25
|
+
size
|
|
26
|
+
});
|
|
27
|
+
const Element = `h${level}`;
|
|
28
|
+
const content = /*#__PURE__*/ jsxRuntime.jsx(Element, {
|
|
29
|
+
...restProps,
|
|
30
|
+
className: cva.cx(className, _className),
|
|
31
|
+
"data-slot": "heading",
|
|
32
|
+
children: innerWrapper ? innerWrapper(children) : children
|
|
33
|
+
});
|
|
34
|
+
return outerWrapper ? outerWrapper(content) : content;
|
|
35
|
+
};
|
|
36
|
+
const ContentContext = /*#__PURE__*/ react.createContext({});
|
|
37
|
+
const Content = ({ ref = null, ...props })=>{
|
|
38
|
+
[props, ref] = reactAriaComponents.useContextProps(props, ref, ContentContext);
|
|
39
|
+
const { _outerWrapper: outerWrapper, ...restProps } = props;
|
|
40
|
+
const content = /*#__PURE__*/ jsxRuntime.jsx("div", {
|
|
41
|
+
...restProps,
|
|
42
|
+
"data-slot": "content"
|
|
43
|
+
});
|
|
44
|
+
return outerWrapper ? outerWrapper(content) : content;
|
|
45
|
+
};
|
|
46
|
+
const mediaVariant = cva.cva({
|
|
47
|
+
variants: {
|
|
48
|
+
/**
|
|
49
|
+
* Control how the content should be placed with the object-fit property
|
|
50
|
+
* You might for example want to use `fit="contain"` portrait images that should not be cropped
|
|
51
|
+
* @default cover
|
|
52
|
+
* */ fit: {
|
|
53
|
+
cover: '*:object-cover',
|
|
54
|
+
contain: '*:object-contain'
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
const MediaContext = /*#__PURE__*/ react.createContext({});
|
|
59
|
+
const Media = ({ ref = null, ...props })=>{
|
|
60
|
+
[props, ref] = reactAriaComponents.useContextProps(props, ref, MediaContext);
|
|
61
|
+
const { className, fit, ...restProps } = props;
|
|
62
|
+
const _className = mediaVariant({
|
|
63
|
+
fit
|
|
64
|
+
});
|
|
65
|
+
return /*#__PURE__*/ jsxRuntime.jsx("div", {
|
|
66
|
+
ref: ref,
|
|
67
|
+
className: cva.cx(className, _className),
|
|
68
|
+
// This can be used (internally) in other components
|
|
69
|
+
// to apply custom styles to the media element depending on the fit
|
|
70
|
+
"data-fit": fit,
|
|
71
|
+
...restProps,
|
|
72
|
+
"data-slot": "media"
|
|
73
|
+
});
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const cardVariants = cva.cva({
|
|
77
|
+
base: [
|
|
78
|
+
'group/card',
|
|
79
|
+
'rounded-[inherit]',
|
|
80
|
+
'border p-3',
|
|
81
|
+
'flex flex-col gap-y-4',
|
|
82
|
+
'relative',
|
|
83
|
+
// **** Content ****
|
|
84
|
+
'[&_[data-slot="content"]]:flex [&_[data-slot="content"]]:flex-col [&_[data-slot="content"]]:gap-y-4',
|
|
85
|
+
// **** Media ****
|
|
86
|
+
'[&_[data-slot="media"]_*]:pointer-events-none',
|
|
87
|
+
'[&_[data-slot="media"]]:overflow-hidden',
|
|
88
|
+
'[&_[data-slot="media"]]:relative',
|
|
89
|
+
// Position media at the edges of the card (because of these negative margins the media-element must be a wrapper around the actual image or other media content)
|
|
90
|
+
'[&_[data-slot="media"]]:mx-[calc(theme(space.3)*-1-theme(borderWidth.DEFAULT))] [&_[data-slot="media"]]:mt-[calc(theme(space.3)*-1-theme(borderWidth.DEFAULT))]',
|
|
91
|
+
// Sets the aspect ratio of the media content (width: 100% is necessary to make aspect ratio work on images in FF)
|
|
92
|
+
'[&_[data-slot="media"]>*:not([data-slot="badge"])]:aspect-3/2 [&_[data-slot="media"]>img]:w-full [&_[data-slot="media"]>img]:object-cover',
|
|
93
|
+
// Prepare zoom animation for hover effects. The hover effect can also be enabled by classes on the parent component, so it is always prepared here.
|
|
94
|
+
'[&_[data-slot="media"]>*]:duration-300 [&_[data-slot="media"]>*]:ease-in-out [&_[data-slot="media"]>*]:motion-safe:transition-transform',
|
|
95
|
+
// **** Card link ****
|
|
96
|
+
// **** Hover ****
|
|
97
|
+
// Enables the zoom hover effect on media (note that we can't use group-hover/card here, because there might be other clickable elements in the card aside from the heading)
|
|
98
|
+
'[&:has([data-slot="card-link"]_a:hover)_[data-slot="media"]>img]:scale-110',
|
|
99
|
+
'[&:has([data-slot="heading"]_[data-slot="card-link"]:hover)_[data-slot="media"]>img]:scale-110',
|
|
100
|
+
// **** Fail-safe for interactive elements ****
|
|
101
|
+
// Make interactive elements clickable by themselves, while the rest of the card is clickable as a whole
|
|
102
|
+
// The card is made clickable by a pseudo-element on the heading that covers the entire card
|
|
103
|
+
'[&_button]:relative [&_input]:relative [&:not(:has([data-slot="card-link"]_a))_a:not([data-slot="card-link"])]:relative',
|
|
104
|
+
// Our Button component has position: relative by default, so we need to override that if it is used in a CardLink (to make the entire card clickable)
|
|
105
|
+
'[&_[data-slot="card-link"]_a]:static',
|
|
106
|
+
// Place other interactive on top of the pseudo-element that makes the entire card clickable
|
|
107
|
+
// by setting a higher z-index than the pseudo-element (which implicitly z-index 0)
|
|
108
|
+
'[&_a:not([data-slot="card-link"])]:z-[1] [&_button]:z-[1] [&_input]:z-[1]',
|
|
109
|
+
// **** Badge ****
|
|
110
|
+
'[&_[data-slot="media"]_[data-slot="badge"]]:absolute [&_[data-slot="media"]_[data-slot="badge"]]:top-0',
|
|
111
|
+
// Increasing z-index Preserves badge position when media content is hovered (the transform scale effect might otherwise move the badge behind the other media content)
|
|
112
|
+
'[&_[data-slot="media"]_[data-slot="badge"]]:z-[1]',
|
|
113
|
+
// Left aligned - override default corner radius of the badge
|
|
114
|
+
'[&_[data-slot="media"]_[data-slot="badge"]:first-child]:rounded-tl-2xl',
|
|
115
|
+
'[&_[data-slot="media"]_[data-slot="badge"]:first-child]:rounded-br-2xl',
|
|
116
|
+
'[&_[data-slot="media"]_[data-slot="badge"]:first-child]:rounded-tr-none',
|
|
117
|
+
'[&_[data-slot="media"]_[data-slot="badge"]:first-child]:rounded-bl-none',
|
|
118
|
+
// Right aligned - override default corner radius of the badge
|
|
119
|
+
'[&_[data-slot="media"]_[data-slot="badge"]:last-child]:rounded-tl-none',
|
|
120
|
+
'[&_[data-slot="media"]_[data-slot="badge"]:last-child]:rounded-br-none',
|
|
121
|
+
'[&_[data-slot="media"]_[data-slot="badge"]:last-child]:rounded-tr-2xl',
|
|
122
|
+
'[&_[data-slot="media"]_[data-slot="badge"]:last-child]:rounded-bl-2xl',
|
|
123
|
+
// ... and position the badge at the right edge of the media content
|
|
124
|
+
'[&_[data-slot="media"]_[data-slot="badge"]:last-child]:right-0'
|
|
125
|
+
],
|
|
126
|
+
variants: {
|
|
127
|
+
/**
|
|
128
|
+
* The variant of the card
|
|
129
|
+
* @default subtle
|
|
130
|
+
*/ variant: {
|
|
131
|
+
subtle: [
|
|
132
|
+
'border-transparent',
|
|
133
|
+
// **** Media styles ****
|
|
134
|
+
'**:data-[slot="media"]:rounded-2xl'
|
|
135
|
+
],
|
|
136
|
+
outlined: 'border border-black'
|
|
137
|
+
},
|
|
138
|
+
/**
|
|
139
|
+
* The layout of the card
|
|
140
|
+
* @default vertical
|
|
141
|
+
*/ layout: {
|
|
142
|
+
vertical: [
|
|
143
|
+
'flex-col',
|
|
144
|
+
// **** Media ****
|
|
145
|
+
'**:data-[slot="media"]:rounded-t-2xl'
|
|
146
|
+
],
|
|
147
|
+
horizontal: [
|
|
148
|
+
// Use more gap for horizontal cards that have media
|
|
149
|
+
// Since this does not affect the layout before the flex direction is set (at breakpoint @2xl for Card with Media), we can set it here
|
|
150
|
+
'has-data-[slot=media]:layout-gap-x not-has-data-[slot=media]:gap-x-4',
|
|
151
|
+
// **** With Media ****
|
|
152
|
+
'[&:has(>[data-slot="media"]:last-child)]:flex-col-reverse',
|
|
153
|
+
'has-data-[slot=media]:@2xl:flex-row!',
|
|
154
|
+
'*:data-[slot=media]:@2xl:h-fit',
|
|
155
|
+
'has-data-[slot=media]:*:@2xl:basis-1/2',
|
|
156
|
+
// Position media at the edges of the card
|
|
157
|
+
'*:data-[slot=media]:@2xl:mb-[calc(theme(space.3)*-1-theme(borderWidth.DEFAULT))]',
|
|
158
|
+
'*:data-[slot=media]:first:@2xl:mr-0',
|
|
159
|
+
'*:data-[slot=media]:last:@2xl:ml-0',
|
|
160
|
+
// Make sure the card link is clickable when the media is on the right side
|
|
161
|
+
// This is necessary because the media content is positioned after the card link in the DOM
|
|
162
|
+
'[&:has(>[data-slot="media"]:last-child)_[data-slot="card-link"]]:z-1',
|
|
163
|
+
// **** Without Media ****
|
|
164
|
+
'not-has-data-[slot=media]:@md:flex-row',
|
|
165
|
+
// Make the layout responsive: when the Content reaches a minimum width of 12rem, the layout switches to vertical. Also makes sure Content takes up the remaining space available.
|
|
166
|
+
'not-has-data-[slot=media]:**:data-[slot=content]:grow',
|
|
167
|
+
// Make sure svg's etc. are not shrinkable
|
|
168
|
+
'[&>:not([data-slot="content"],[data-slot="media"])]:shrink-0'
|
|
169
|
+
]
|
|
170
|
+
}
|
|
171
|
+
},
|
|
172
|
+
defaultVariants: {
|
|
173
|
+
variant: 'subtle',
|
|
174
|
+
layout: 'vertical'
|
|
175
|
+
},
|
|
176
|
+
compoundVariants: [
|
|
177
|
+
{
|
|
178
|
+
variant: 'outlined',
|
|
179
|
+
layout: 'horizontal',
|
|
180
|
+
className: [
|
|
181
|
+
// **** Media ****
|
|
182
|
+
// Some rounded corners are removed when the card is outlined
|
|
183
|
+
'**:data-[slot="media"]:rounded-t-2xl',
|
|
184
|
+
'*:data-[slot=media]:first:@2xl:rounded-tr-none *:data-[slot=media]:first:@2xl:rounded-bl-2xl',
|
|
185
|
+
'*:data-[slot=media]:last:@2xl:rounded-tl-none *:data-[slot=media]:last:@2xl:rounded-br-2xl',
|
|
186
|
+
// **** Badge ****
|
|
187
|
+
// Override default corner radius of the badge to match the media border radius
|
|
188
|
+
'[&_[data-slot="media"]:first-child_[data-slot="badge"]:last-child]:@2xl:rounded-tr-none',
|
|
189
|
+
'[&_[data-slot="media"]:last-child_[data-slot="badge"]:first-child]:@2xl:rounded-tl-none'
|
|
190
|
+
]
|
|
191
|
+
}
|
|
192
|
+
]
|
|
193
|
+
});
|
|
194
|
+
const Card = ({ children, className, variant, layout, ...restProps })=>{
|
|
195
|
+
const cardClassName = cardVariants({
|
|
196
|
+
variant,
|
|
197
|
+
layout
|
|
198
|
+
});
|
|
199
|
+
return(// The border-radius is set on the outer container to make it act as an invisible wrapper, only used for container queries
|
|
200
|
+
// Since passing the className prop to this container is necessary to make custom styles behave as expected, we need to apply the border-radius here incase the consumer passes a custom background color
|
|
201
|
+
/*#__PURE__*/ jsxRuntime.jsx("div", {
|
|
202
|
+
...restProps,
|
|
203
|
+
className: cva.cx(className, '@container rounded-2xl'),
|
|
204
|
+
children: /*#__PURE__*/ jsxRuntime.jsx("div", {
|
|
205
|
+
className: cardClassName,
|
|
206
|
+
children: /*#__PURE__*/ jsxRuntime.jsx(reactAriaComponents.Provider, {
|
|
207
|
+
values: [
|
|
208
|
+
[
|
|
209
|
+
HeadingContext,
|
|
210
|
+
{
|
|
211
|
+
size: 's',
|
|
212
|
+
className: cva.cx([
|
|
213
|
+
'inline',
|
|
214
|
+
'w-fit',
|
|
215
|
+
'text-pretty',
|
|
216
|
+
'hyphens-auto',
|
|
217
|
+
'[word-break:break-word]',
|
|
218
|
+
// **** Card link in Heading ****
|
|
219
|
+
// Border (bottom/top) is set to transparent to make sure the bottom underline is not visible when the card is hovered
|
|
220
|
+
// Border top is set to even out the border bottom used for the underline
|
|
221
|
+
'*:data-[slot="card-link"]:no-underline',
|
|
222
|
+
'*:data-[slot="card-link"]:border-y-2',
|
|
223
|
+
'*:data-[slot="card-link"]:border-y-transparent',
|
|
224
|
+
'*:data-[slot="card-link"]:transition-colors',
|
|
225
|
+
'*:data-[slot="card-link"]:hover:border-b-current',
|
|
226
|
+
// Mimic heading styles for the card link if placed in the heading slot. This is necessary to make the custom underline align with the link text
|
|
227
|
+
'*:data-[slot="card-link"]:font-inherit',
|
|
228
|
+
'*:data-[slot="card-link"]:text-pretty',
|
|
229
|
+
'*:data-[slot="card-link"]:hyphens-auto',
|
|
230
|
+
'*:data-[slot="card-link"]:[word-break:break-word]'
|
|
231
|
+
])
|
|
232
|
+
}
|
|
233
|
+
]
|
|
234
|
+
],
|
|
235
|
+
children: children
|
|
236
|
+
})
|
|
237
|
+
})
|
|
238
|
+
}));
|
|
239
|
+
};
|
|
240
|
+
const cardLinkVariants = cva.cva({
|
|
241
|
+
base: 'w-fit max-w-full',
|
|
242
|
+
variants: {
|
|
243
|
+
withHref: {
|
|
244
|
+
true: [
|
|
245
|
+
// **** Clickarea ****
|
|
246
|
+
'cursor-pointer',
|
|
247
|
+
'after:absolute',
|
|
248
|
+
'after:-inset-px',
|
|
249
|
+
'after:rounded-[calc(var(--radius-2xl)-theme(borderWidth.DEFAULT))]',
|
|
250
|
+
// **** Focus ****
|
|
251
|
+
'focus-visible:outline-none',
|
|
252
|
+
'data-focus-visible:after:outline-focus',
|
|
253
|
+
'data-focus-visible:after:outline-offset-2',
|
|
254
|
+
// **** Hover ****
|
|
255
|
+
// Links are underlined by default, and the underline is removed on hover.
|
|
256
|
+
// So we make sure that also happens when the user hovers the clickable area.
|
|
257
|
+
'hover:no-underline'
|
|
258
|
+
],
|
|
259
|
+
false: [
|
|
260
|
+
// **** Clickarea ****
|
|
261
|
+
'[&_a]:after:cursor-pointer',
|
|
262
|
+
'[&_a]:after:absolute',
|
|
263
|
+
'[&_a]:after:-inset-px',
|
|
264
|
+
'[&_a]:after:rounded-[calc(var(--radius-2xl)-theme(borderWidth.DEFAULT))]',
|
|
265
|
+
// **** Focus ****
|
|
266
|
+
'[&_a[data-focus-visible]]:outline-none',
|
|
267
|
+
'[&_a[data-focus-visible]]:after:outline-focus',
|
|
268
|
+
'[&_a[data-focus-visible]]:after:outline-offset-2',
|
|
269
|
+
// **** Hover ****
|
|
270
|
+
// Links are underlined by default, and the underline is removed on hover.
|
|
271
|
+
// So we make sure that also happens when the user hovers the card.
|
|
272
|
+
// The group-hover ensures that the hover effect also applies when this component is used as a wrapper around a link.
|
|
273
|
+
'[&_a]:group-hover/card:no-underline'
|
|
274
|
+
]
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
});
|
|
278
|
+
/**
|
|
279
|
+
* A component that creates a clickable area on a card.
|
|
280
|
+
* It can be used either as a wrapper around a link or as a standalone link.
|
|
281
|
+
*/ const CardLink = ({ className: _className, href, ...restProps })=>{
|
|
282
|
+
const className = cardLinkVariants({
|
|
283
|
+
className: _className,
|
|
284
|
+
withHref: !!href
|
|
285
|
+
});
|
|
286
|
+
return href ? /*#__PURE__*/ jsxRuntime.jsx(reactAriaComponents.Link, {
|
|
287
|
+
"data-slot": "card-link",
|
|
288
|
+
...restProps,
|
|
289
|
+
href: href,
|
|
290
|
+
className: className
|
|
291
|
+
}) : // We can't utilize that the `Link` component from react-aria-components renders as a span if it doesn't have an href,
|
|
292
|
+
// because it still renders with role="link" and tabindex="0" which makes it focusable.
|
|
293
|
+
// So we need to render a div instead.
|
|
294
|
+
/*#__PURE__*/ jsxRuntime.jsx("div", {
|
|
295
|
+
...restProps,
|
|
296
|
+
"data-slot": "card-link",
|
|
297
|
+
className: className
|
|
298
|
+
});
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
const HeroContext = /*#__PURE__*/ react.createContext(null);
|
|
302
|
+
// Common variant for "standard" and "full-bleed" Hero variants
|
|
303
|
+
const oneColumnLayout = [
|
|
304
|
+
// Vertical spacing in the <Content>
|
|
305
|
+
'lg:*:data-[slot=content]:gap-y-4',
|
|
306
|
+
// Main text content takes up 9 columns on medium screens and above
|
|
307
|
+
'lg:*:data-[slot=content]:col-span-9',
|
|
308
|
+
// Make sure other elements than <Content> and <Media> (i.e CTA) does not span the full width on small screens
|
|
309
|
+
'*:not-data-[slot=content]:not-data-[slot=media]:w-fit',
|
|
310
|
+
// Other elements than <Content> and <Media> (e.g. CTA, SVG logo or Badge) take up 3 columns on medium screens and above, and are right aligned
|
|
311
|
+
'lg:*:not-data-[slot=content]:not-data-[slot=media]:not-data-[slot=carousel]:col-span-3 lg:*:not-data-[slot=content]:not-data-[slot=media]:justify-self-end',
|
|
312
|
+
// <Media> and <Carousel> content takes up the full width on medium screens and above
|
|
313
|
+
'lg:*:data-[slot=media]:col-span-full *:data-[slot=media]:*:w-full',
|
|
314
|
+
'lg:*:data-[slot=carousel]:col-span-full',
|
|
315
|
+
// Aligns <Content> and any element beside it (e.g. <Media>, <Badge>, <CTA> etc.) to the bottom of the <Content> container
|
|
316
|
+
'lg:items-end'
|
|
317
|
+
];
|
|
318
|
+
const nonFullBleedAspectRatiosForSmallScreens = '*:data-[slot=media]:not-has-data-[slot=video]:*:aspect-[1/1] sm:*:data-[slot=media]:not-has-data-[slot=video]:*:aspect-4/3 md:*:data-[slot=media]:not-has-data-[slot=video]:*:aspect-3/2';
|
|
319
|
+
const variants = cva.cva({
|
|
320
|
+
base: [
|
|
321
|
+
'container px-0',
|
|
322
|
+
// Grid variant to position the Hero's content
|
|
323
|
+
'grid lg:grid-cols-12 lg:gap-x-12 xl:gap-x-16',
|
|
324
|
+
'gap-y-10 lg:gap-y-12',
|
|
325
|
+
// Enable vertical gap within <Content>
|
|
326
|
+
'*:data-[slot=content]:grid',
|
|
327
|
+
// Vertical spacing in the <Content>
|
|
328
|
+
'*:data-[slot=content]:gap-y-3',
|
|
329
|
+
// Make sure <Media> content fills any available vertical and horizontal space
|
|
330
|
+
'*:data-[slot=media]:*:object-cover',
|
|
331
|
+
'*:data-[slot=carousel]:overflow-hidden *:data-[slot=carousel]:rounded-3xl',
|
|
332
|
+
// Make the carousel items full width, so we scroll one at a time
|
|
333
|
+
'**:data-[slot=carousel-item]:basis-full'
|
|
334
|
+
],
|
|
335
|
+
variants: {
|
|
336
|
+
/**
|
|
337
|
+
* Defines the variant of the Hero
|
|
338
|
+
* @default standard
|
|
339
|
+
* */ variant: {
|
|
340
|
+
standard: [
|
|
341
|
+
oneColumnLayout,
|
|
342
|
+
nonFullBleedAspectRatiosForSmallScreens,
|
|
343
|
+
'lg:*:data-[slot=media]:not-has-data-[slot=video]:*:aspect-2/1'
|
|
344
|
+
],
|
|
345
|
+
'full-bleed': [
|
|
346
|
+
oneColumnLayout,
|
|
347
|
+
// Position the media and carousel content to fill the entire viewport width
|
|
348
|
+
'*:data-[slot=media]:*:absolute *:data-[slot=media]:*:left-0',
|
|
349
|
+
// Special case for Carousel, where the Media is nested inside a CarouselItem
|
|
350
|
+
'*:data-[slot=carousel]:**:data-[slot=media]:w-full',
|
|
351
|
+
// Match the heights of the <Media> or <Carousel> wrapper for the Media content (e.g. image, VideoLoop, video etc.)
|
|
352
|
+
// This is necessary due to the absolute positioning of the media and carousel containers in this variant
|
|
353
|
+
// biome-ignore lint/nursery/useSortedClasses: biome is unable to sort the custom classes for 3xl and 4xl breakpoints
|
|
354
|
+
'3xl:**:data-[slot=media]:h-192 4xl:**:data-[slot=media]:h-212 **:data-[slot=media]:h-80 sm:**:data-[slot=media]:h-100 md:**:data-[slot=media]:h-120 lg:**:data-[slot=media]:h-140 xl:**:data-[slot=media]:h-160 2xl:**:data-[slot=media]:h-168',
|
|
355
|
+
'**:data-[slot=media]:*:h-[inherit]',
|
|
356
|
+
// biome-ignore lint/nursery/useSortedClasses: biome is unable to sort the custom classes for 3xl and 4xl breakpoints
|
|
357
|
+
'3xl:*:data-[slot=carousel]:h-192 4xl:*:data-[slot=carousel]:h-212 *:data-[slot=carousel]:h-80 sm:*:data-[slot=carousel]:h-100 md:*:data-[slot=carousel]:h-120 lg:*:data-[slot=carousel]:h-140 xl:*:data-[slot=carousel]:h-160 2xl:*:data-[slot=carousel]:h-168',
|
|
358
|
+
'*:data-[slot=carousel]:w-full!',
|
|
359
|
+
// Override aspect ratio of the media and carousel-item slots (since we can not use aspect for full-bleed layout)
|
|
360
|
+
'**:data-[slot=carousel-item]:data-[slot=media]:*:aspect-none',
|
|
361
|
+
// break out the carousel out of the container
|
|
362
|
+
'**:data-[slot=carousel-items-container]:absolute **:data-[slot=carousel-items-container]:inset-x-0 **:data-[slot=carousel-items-container]:h-[inherit]',
|
|
363
|
+
// Positions the carousel controls inside the carousel
|
|
364
|
+
'*:data-[slot=carousel]:flex *:data-[slot=carousel]:items-end *:data-[slot=carousel]:justify-end **:data-[slot=carousel-controls]:z-10 **:data-[slot=carousel-controls]:mb-4'
|
|
365
|
+
],
|
|
366
|
+
'two-column': [
|
|
367
|
+
'lg:items-center lg:*:col-span-6',
|
|
368
|
+
// Vertical spacing in the <Content>
|
|
369
|
+
'lg:*:data-[slot=content]:gap-y-7',
|
|
370
|
+
nonFullBleedAspectRatiosForSmallScreens,
|
|
371
|
+
// Set media aspect ratio to 1:1 (square)
|
|
372
|
+
'lg:*:data-[slot=media]:not-has-data-[slot=video]:*:aspect-square'
|
|
373
|
+
]
|
|
374
|
+
}
|
|
375
|
+
},
|
|
376
|
+
compoundVariants: [
|
|
377
|
+
{
|
|
378
|
+
variant: [
|
|
379
|
+
'standard',
|
|
380
|
+
'two-column'
|
|
381
|
+
],
|
|
382
|
+
className: [
|
|
383
|
+
'*:data-[slot=media]:*:rounded-3xl',
|
|
384
|
+
'*:data-[slot=carousel]:relative **:data-[slot=carousel-container]:rounded-3xl **:data-[slot=carousel-controls]:absolute **:data-[slot=carousel-controls]:right-4 **:data-[slot=carousel-controls]:bottom-4'
|
|
385
|
+
]
|
|
386
|
+
}
|
|
387
|
+
],
|
|
388
|
+
defaultVariants: {
|
|
389
|
+
variant: 'standard'
|
|
390
|
+
}
|
|
391
|
+
});
|
|
392
|
+
const Hero = ({ variant, className, children, ...rest })=>{
|
|
393
|
+
const variantsClassName = variants({
|
|
394
|
+
variant,
|
|
395
|
+
className
|
|
396
|
+
});
|
|
397
|
+
return /*#__PURE__*/ jsxRuntime.jsx(reactAriaComponents.Provider, {
|
|
398
|
+
values: [
|
|
399
|
+
[
|
|
400
|
+
HeroContext,
|
|
401
|
+
{
|
|
402
|
+
variant
|
|
403
|
+
}
|
|
404
|
+
],
|
|
405
|
+
[
|
|
406
|
+
HeadingContext,
|
|
407
|
+
{
|
|
408
|
+
// Sets the default heading size for the Hero based on the variant
|
|
409
|
+
size: variant === 'two-column' ? 'xl' : 'l',
|
|
410
|
+
className: // word-break:break-word to allow long words to break (this is necessary to make hyphens work in grid containers in Safari)
|
|
411
|
+
'hyphens-auto text-pretty [word-break:break-word]'
|
|
412
|
+
}
|
|
413
|
+
],
|
|
414
|
+
[
|
|
415
|
+
reactAriaComponents.GroupContext,
|
|
416
|
+
{
|
|
417
|
+
// Prevents the group from being announced as a group by screen readers
|
|
418
|
+
// The Group component is used to group the Hero's CTA buttons together visually, and has no semantic meaning
|
|
419
|
+
role: 'presentation',
|
|
420
|
+
className: 'flex flex-wrap gap-3 *:w-fit'
|
|
421
|
+
}
|
|
422
|
+
]
|
|
423
|
+
],
|
|
424
|
+
children: /*#__PURE__*/ jsxRuntime.jsx("div", {
|
|
425
|
+
className: cva.cx(variantsClassName, className),
|
|
426
|
+
...rest,
|
|
427
|
+
children: children
|
|
428
|
+
})
|
|
429
|
+
});
|
|
430
|
+
};
|
|
431
|
+
|
|
432
|
+
const meta = {
|
|
433
|
+
title: 'Layout'
|
|
434
|
+
};
|
|
435
|
+
const GridContainer = ()=>/*#__PURE__*/ jsxRuntime.jsx("main", {
|
|
436
|
+
className: "layout-grid-container",
|
|
437
|
+
children: /*#__PURE__*/ jsxRuntime.jsxs(Hero, {
|
|
438
|
+
children: [
|
|
439
|
+
/*#__PURE__*/ jsxRuntime.jsxs(Content, {
|
|
440
|
+
children: [
|
|
441
|
+
/*#__PURE__*/ jsxRuntime.jsx(Heading, {
|
|
442
|
+
level: 1,
|
|
443
|
+
size: "xl",
|
|
444
|
+
children: "Jobb i OBOS"
|
|
445
|
+
}),
|
|
446
|
+
/*#__PURE__*/ jsxRuntime.jsx("p", {
|
|
447
|
+
className: "lead",
|
|
448
|
+
children: "Bli med å oppfylle boligdrømmer! Vi søker engasjerte og dyktige personer som vil ta OBOS videre. Søk på våre ledige stillinger!"
|
|
449
|
+
})
|
|
450
|
+
]
|
|
451
|
+
}),
|
|
452
|
+
/*#__PURE__*/ jsxRuntime.jsx(Media, {
|
|
453
|
+
children: /*#__PURE__*/ jsxRuntime.jsx("img", {
|
|
454
|
+
src: "https://cdn.sanity.io/media-libraries/mln4u7f3Hc8r/images/410001cfde5211194e0072bf39abd3214befb1c2-1920x1080.jpg?auto=format",
|
|
455
|
+
alt: ""
|
|
456
|
+
})
|
|
457
|
+
})
|
|
458
|
+
]
|
|
459
|
+
})
|
|
460
|
+
});
|
|
461
|
+
const GridContainerWithSubGrids = ()=>/*#__PURE__*/ jsxRuntime.jsxs("main", {
|
|
462
|
+
className: "layout-grid-container layout-gap-y",
|
|
463
|
+
children: [
|
|
464
|
+
/*#__PURE__*/ jsxRuntime.jsx("h1", {
|
|
465
|
+
className: "heading-xl sm:col-end-9",
|
|
466
|
+
children: "Dette er OBOS"
|
|
467
|
+
}),
|
|
468
|
+
/*#__PURE__*/ jsxRuntime.jsxs("ul", {
|
|
469
|
+
className: "md:layout-subgrid-12 *:md:col-span-6 *:lg:col-span-3",
|
|
470
|
+
children: [
|
|
471
|
+
/*#__PURE__*/ jsxRuntime.jsxs(Card, {
|
|
472
|
+
role: "listitem",
|
|
473
|
+
children: [
|
|
474
|
+
/*#__PURE__*/ jsxRuntime.jsxs(Content, {
|
|
475
|
+
children: [
|
|
476
|
+
/*#__PURE__*/ jsxRuntime.jsx(Heading, {
|
|
477
|
+
level: 2,
|
|
478
|
+
children: /*#__PURE__*/ jsxRuntime.jsx(CardLink, {
|
|
479
|
+
href: "/bolig",
|
|
480
|
+
children: "Bolig"
|
|
481
|
+
})
|
|
482
|
+
}),
|
|
483
|
+
/*#__PURE__*/ jsxRuntime.jsx("p", {
|
|
484
|
+
children: "Oppfyll boligdrømmen med OBOS!"
|
|
485
|
+
})
|
|
486
|
+
]
|
|
487
|
+
}),
|
|
488
|
+
/*#__PURE__*/ jsxRuntime.jsx(grunnmurenIconsReact.ArrowRight, {
|
|
489
|
+
className: "transition-transform group-hover/card:motion-safe:translate-x-1"
|
|
490
|
+
})
|
|
491
|
+
]
|
|
492
|
+
}),
|
|
493
|
+
/*#__PURE__*/ jsxRuntime.jsxs(Card, {
|
|
494
|
+
role: "listitem",
|
|
495
|
+
children: [
|
|
496
|
+
/*#__PURE__*/ jsxRuntime.jsxs(Content, {
|
|
497
|
+
children: [
|
|
498
|
+
/*#__PURE__*/ jsxRuntime.jsx(Heading, {
|
|
499
|
+
level: 2,
|
|
500
|
+
children: /*#__PURE__*/ jsxRuntime.jsx(CardLink, {
|
|
501
|
+
href: "/medlem",
|
|
502
|
+
children: "Medlem"
|
|
503
|
+
})
|
|
504
|
+
}),
|
|
505
|
+
/*#__PURE__*/ jsxRuntime.jsx("p", {
|
|
506
|
+
children: "Bli medlem i OBOS og få tilgang til eksklusive fordeler!"
|
|
507
|
+
})
|
|
508
|
+
]
|
|
509
|
+
}),
|
|
510
|
+
/*#__PURE__*/ jsxRuntime.jsx(grunnmurenIconsReact.ArrowRight, {
|
|
511
|
+
className: "transition-transform group-hover/card:motion-safe:translate-x-1"
|
|
512
|
+
})
|
|
513
|
+
]
|
|
514
|
+
}),
|
|
515
|
+
/*#__PURE__*/ jsxRuntime.jsxs(Card, {
|
|
516
|
+
role: "listitem",
|
|
517
|
+
children: [
|
|
518
|
+
/*#__PURE__*/ jsxRuntime.jsxs(Content, {
|
|
519
|
+
children: [
|
|
520
|
+
/*#__PURE__*/ jsxRuntime.jsx(Heading, {
|
|
521
|
+
level: 2,
|
|
522
|
+
children: /*#__PURE__*/ jsxRuntime.jsx(CardLink, {
|
|
523
|
+
href: "/bli-bankkunde",
|
|
524
|
+
children: "Bank"
|
|
525
|
+
})
|
|
526
|
+
}),
|
|
527
|
+
/*#__PURE__*/ jsxRuntime.jsx("p", {
|
|
528
|
+
children: "OBOS Bank tilbyr konkurransedyktige rente på boliglån og sparekonto!"
|
|
529
|
+
})
|
|
530
|
+
]
|
|
531
|
+
}),
|
|
532
|
+
/*#__PURE__*/ jsxRuntime.jsx(grunnmurenIconsReact.ArrowRight, {
|
|
533
|
+
className: "transition-transform group-hover/card:motion-safe:translate-x-1"
|
|
534
|
+
})
|
|
535
|
+
]
|
|
536
|
+
}),
|
|
537
|
+
/*#__PURE__*/ jsxRuntime.jsxs(Card, {
|
|
538
|
+
role: "listitem",
|
|
539
|
+
children: [
|
|
540
|
+
/*#__PURE__*/ jsxRuntime.jsxs(Content, {
|
|
541
|
+
children: [
|
|
542
|
+
/*#__PURE__*/ jsxRuntime.jsx(Heading, {
|
|
543
|
+
level: 2,
|
|
544
|
+
children: /*#__PURE__*/ jsxRuntime.jsx(CardLink, {
|
|
545
|
+
href: "/medlem-i-obos",
|
|
546
|
+
children: "Forkjøp"
|
|
547
|
+
})
|
|
548
|
+
}),
|
|
549
|
+
/*#__PURE__*/ jsxRuntime.jsx("p", {
|
|
550
|
+
children: "Som medlem i OBOS har du forkjøpsrett på tusenvis av boliger hvert år!"
|
|
551
|
+
})
|
|
552
|
+
]
|
|
553
|
+
}),
|
|
554
|
+
/*#__PURE__*/ jsxRuntime.jsx(grunnmurenIconsReact.ArrowRight, {
|
|
555
|
+
className: "transition-transform group-hover/card:motion-safe:translate-x-1"
|
|
556
|
+
})
|
|
557
|
+
]
|
|
558
|
+
})
|
|
559
|
+
]
|
|
560
|
+
})
|
|
561
|
+
]
|
|
562
|
+
});
|
|
563
|
+
const OverridedColSpans = ()=>/*#__PURE__*/ jsxRuntime.jsxs("main", {
|
|
564
|
+
className: "layout-grid-container",
|
|
565
|
+
children: [
|
|
566
|
+
/*#__PURE__*/ jsxRuntime.jsx("h1", {
|
|
567
|
+
className: "heading-xl sm:col-end-9",
|
|
568
|
+
children: "Dette er OBOS"
|
|
569
|
+
}),
|
|
570
|
+
/*#__PURE__*/ jsxRuntime.jsx("img", {
|
|
571
|
+
className: "sm:col-end-8",
|
|
572
|
+
src: "https://cdn.sanity.io/media-libraries/mln4u7f3Hc8r/images/410001cfde5211194e0072bf39abd3214befb1c2-1920x1080.jpg?auto=format",
|
|
573
|
+
alt: ""
|
|
574
|
+
}),
|
|
575
|
+
/*#__PURE__*/ jsxRuntime.jsx("p", {
|
|
576
|
+
className: "sm:col-start-6 sm:col-end-12",
|
|
577
|
+
children: "Som er ett nettsted for alt om OBOS."
|
|
578
|
+
}),
|
|
579
|
+
/*#__PURE__*/ jsxRuntime.jsx("img", {
|
|
580
|
+
className: "sm:col-span-6 sm:col-start-6",
|
|
581
|
+
src: "https://cdn.sanity.io/media-libraries/mln4u7f3Hc8r/images/410001cfde5211194e0072bf39abd3214befb1c2-1920x1080.jpg?auto=format",
|
|
582
|
+
alt: ""
|
|
583
|
+
}),
|
|
584
|
+
/*#__PURE__*/ jsxRuntime.jsx("p", {
|
|
585
|
+
className: "sm:col-end-15",
|
|
586
|
+
children: "Masse tekst for å teste grid container med sub grids. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
|
|
587
|
+
}),
|
|
588
|
+
/*#__PURE__*/ jsxRuntime.jsx("img", {
|
|
589
|
+
className: "sm:col-span-full",
|
|
590
|
+
src: "https://cdn.sanity.io/media-libraries/mln4u7f3Hc8r/images/410001cfde5211194e0072bf39abd3214befb1c2-1920x1080.jpg?auto=format",
|
|
591
|
+
alt: ""
|
|
592
|
+
})
|
|
593
|
+
]
|
|
594
|
+
});
|
|
595
|
+
|
|
596
|
+
exports.GridContainer = GridContainer;
|
|
597
|
+
exports.GridContainerWithSubGrids = GridContainerWithSubGrids;
|
|
598
|
+
exports.OverridedColSpans = OverridedColSpans;
|
|
599
|
+
exports.default = meta;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { Meta } from '@storybook/react-vite';
|
|
3
|
+
|
|
4
|
+
declare const meta: Meta;
|
|
5
|
+
|
|
6
|
+
declare const GridContainer: () => react_jsx_runtime.JSX.Element;
|
|
7
|
+
declare const GridContainerWithSubGrids: () => react_jsx_runtime.JSX.Element;
|
|
8
|
+
declare const OverridedColSpans: () => react_jsx_runtime.JSX.Element;
|
|
9
|
+
|
|
10
|
+
export { GridContainer, GridContainerWithSubGrids, OverridedColSpans, meta as default };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { Meta } from '@storybook/react-vite';
|
|
3
|
+
|
|
4
|
+
declare const meta: Meta;
|
|
5
|
+
|
|
6
|
+
declare const GridContainer: () => react_jsx_runtime.JSX.Element;
|
|
7
|
+
declare const GridContainerWithSubGrids: () => react_jsx_runtime.JSX.Element;
|
|
8
|
+
declare const OverridedColSpans: () => react_jsx_runtime.JSX.Element;
|
|
9
|
+
|
|
10
|
+
export { GridContainer, GridContainerWithSubGrids, OverridedColSpans, meta as default };
|