@arkitektbedriftene/fe-lib 0.3.4 → 0.3.5

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arkitektbedriftene/fe-lib",
3
- "version": "0.3.4",
3
+ "version": "0.3.5",
4
4
  "type": "module",
5
5
  "main": "./dist/index.umd.cjs",
6
6
  "module": "./dist/index.es.js",
@@ -54,6 +54,7 @@
54
54
  "peerDependencies": {
55
55
  "react": "^18.2.0",
56
56
  "react-dom": "^18.2.0",
57
+ "@floating-ui/react": "^0.26.0",
57
58
  "lexical": "^0.12.0",
58
59
  "@lexical/headless": "^0.12.0",
59
60
  "@lexical/html": "^0.12.0",
@@ -9,15 +9,23 @@ const AlertStyled = styled("div", {
9
9
  color: {
10
10
  warning: {
11
11
  background: "$yellow200",
12
- color: "#000",
12
+ border: "1px solid $yellow400",
13
+ color: "$yellow900",
13
14
  },
14
15
  danger: {
15
- background: "$red600",
16
- color: "#fff",
16
+ background: "$red200",
17
+ border: "1px solid $red400",
18
+ color: "$red900",
17
19
  },
18
20
  info: {
19
21
  background: "$blue200",
20
- color: "#000",
22
+ border: "1px solid $blue400",
23
+ color: "$blue900",
24
+ },
25
+ success: {
26
+ background: "$green200",
27
+ border: "1px solid $green400",
28
+ color: "$green900",
21
29
  },
22
30
  },
23
31
  size: {
@@ -0,0 +1,3 @@
1
+ import { styled } from "../stitches.config";
2
+
3
+ export const Box = styled("div");
@@ -135,8 +135,30 @@ const ButtonStyled = styled("button", {
135
135
  },
136
136
  },
137
137
  },
138
+ icon: {
139
+ true: {}
140
+ }
138
141
  },
139
142
 
143
+ compoundVariants: [
144
+ {
145
+ icon: true,
146
+ size: "md",
147
+ css: {
148
+ padding: "$2",
149
+ width: "2.25rem",
150
+ }
151
+ },
152
+ {
153
+ icon: true,
154
+ size: "lg",
155
+ css: {
156
+ padding: "$2",
157
+ width: "2.75rem",
158
+ }
159
+ },
160
+ ],
161
+
140
162
  defaultVariants: {
141
163
  variant: "outline",
142
164
  color: "secondary",
@@ -0,0 +1,50 @@
1
+ import { css, keyframes, styled } from "../stitches.config";
2
+
3
+ // Animation
4
+ const slideUpAndFade = keyframes({
5
+ "0%": { opacity: 0, transform: "translateY(0.5rem)" },
6
+ "100%": { opacity: 1, transform: "translateY(0)" },
7
+ });
8
+
9
+ const slideRightAndFade = keyframes({
10
+ "0%": { opacity: 0, transform: "translateX(-0.5rem)" },
11
+ "100%": { opacity: 1, transform: "translateX(0)" },
12
+ });
13
+
14
+ const slideDownAndFade = keyframes({
15
+ "0%": { opacity: 0, transform: "translateY(-0.5rem)" },
16
+ "100%": { opacity: 1, transform: "translateY(0)" },
17
+ });
18
+
19
+ const slideLeftAndFade = keyframes({
20
+ "0%": { opacity: 0, transform: "translateX(0.5rem)" },
21
+ "100%": { opacity: 1, transform: "translateX(0)" },
22
+ });
23
+
24
+ const overlayCardCss = css({
25
+ backgroundColor: "white",
26
+ boxShadow: "$overlayCard",
27
+ borderRadius: "$sm",
28
+ overflow: "hidden",
29
+ zIndex: "$overlayCard",
30
+ });
31
+
32
+ const overlayCardAnimationCss = css({
33
+ animationDuration: "400ms",
34
+ animationTimingFunction: "cubic-bezier(0.16, 1, 0.3, 1)",
35
+ willChange: "transform, opacity",
36
+ '&[data-state="open"]': {
37
+ '&[data-side="top"]': { animationName: slideDownAndFade },
38
+ '&[data-side="right"]': { animationName: slideLeftAndFade },
39
+ '&[data-side="bottom"]': { animationName: slideUpAndFade },
40
+ '&[data-side="left"]': { animationName: slideRightAndFade },
41
+ },
42
+ });
43
+
44
+ export const OverlayCard = styled(
45
+ "div",
46
+ overlayCardCss,
47
+ overlayCardAnimationCss,
48
+ );
49
+
50
+ export type OverlayCardProps = React.ComponentProps<typeof OverlayCard>;
@@ -0,0 +1,164 @@
1
+ import {
2
+ FloatingPortal,
3
+ type OffsetOptions,
4
+ type Placement,
5
+ autoUpdate,
6
+ flip,
7
+ offset,
8
+ safePolygon,
9
+ shift,
10
+ useClick,
11
+ useDismiss,
12
+ useFloating,
13
+ useHover,
14
+ useInteractions,
15
+ useRole,
16
+ useTransitionStyles,
17
+ type UseRoleProps,
18
+ } from "@floating-ui/react";
19
+ import {
20
+ cloneElement,
21
+ createContext,
22
+ isValidElement,
23
+ useContext,
24
+ useMemo,
25
+ } from "react";
26
+ import { OverlayCard, type OverlayCardProps } from "./OverlayCard";
27
+ import { Box } from "./Box";
28
+
29
+ type PopoverContextValue = {
30
+ getFloatingProps: ReturnType<typeof useInteractions>["getFloatingProps"];
31
+ getReferenceProps: ReturnType<typeof useInteractions>["getReferenceProps"];
32
+ floatingStyles: ReturnType<typeof useFloating>["floatingStyles"];
33
+ refs: ReturnType<typeof useFloating>["refs"];
34
+ isMounted: boolean;
35
+ transitionStyles: ReturnType<typeof useTransitionStyles>["styles"];
36
+ };
37
+
38
+ const PopoverContext = createContext<PopoverContextValue>(
39
+ {} as PopoverContextValue,
40
+ );
41
+
42
+ export const Popover = ({
43
+ children,
44
+ offset: offsetOptions,
45
+ open,
46
+ onOpenChange,
47
+ trigger = "click",
48
+ hoverDelay,
49
+ placement = "bottom",
50
+ role: popoverRole = "dialog",
51
+ }: {
52
+ children: React.ReactNode;
53
+ offset?: OffsetOptions;
54
+ open: boolean;
55
+ onOpenChange: (open: boolean) => void;
56
+ trigger?: "click" | "hover";
57
+ hoverDelay?: number | { open: number; close: number };
58
+ placement?: Placement;
59
+ role?: UseRoleProps["role"];
60
+ }) => {
61
+ const { refs, floatingStyles, context } = useFloating({
62
+ open,
63
+ onOpenChange,
64
+ placement,
65
+ whileElementsMounted: autoUpdate,
66
+ middleware: [offset(offsetOptions), flip(), shift()],
67
+ });
68
+
69
+ const { isMounted, styles: transitionStyles } = useTransitionStyles(context, {
70
+ initial: ({ side }) => ({
71
+ opacity: 0,
72
+ transform: {
73
+ top: "translateY(-0.5rem)",
74
+ right: "translateX(0.5rem)",
75
+ bottom: "translateY(0.5rem)",
76
+ left: "translateX(-0.5rem)",
77
+ }[side],
78
+ }),
79
+ });
80
+
81
+ const click = useClick(context, { enabled: trigger === "click" });
82
+ const hover = useHover(context, {
83
+ enabled: trigger === "hover",
84
+ delay: hoverDelay,
85
+ handleClose: safePolygon(),
86
+ });
87
+ const dismiss = useDismiss(context);
88
+ const role = useRole(context, { role: popoverRole });
89
+
90
+ const { getFloatingProps, getReferenceProps } = useInteractions([
91
+ click,
92
+ hover,
93
+ dismiss,
94
+ role,
95
+ ]);
96
+
97
+ const contextValue = useMemo(
98
+ () => ({
99
+ getFloatingProps,
100
+ getReferenceProps,
101
+ floatingStyles,
102
+ refs,
103
+ isMounted,
104
+ transitionStyles,
105
+ }),
106
+ [
107
+ getFloatingProps,
108
+ getReferenceProps,
109
+ isMounted,
110
+ refs,
111
+ floatingStyles,
112
+ transitionStyles,
113
+ ],
114
+ );
115
+
116
+ return (
117
+ <PopoverContext.Provider value={contextValue}>
118
+ {children}
119
+ </PopoverContext.Provider>
120
+ );
121
+ };
122
+
123
+ export const PopoverTrigger = ({ children }: { children: React.ReactNode }) => {
124
+ const { getReferenceProps, refs } = useContext(PopoverContext);
125
+
126
+ return (
127
+ <>
128
+ {isValidElement(children) &&
129
+ cloneElement(children as React.ReactElement, {
130
+ ref: refs.setReference,
131
+ ...getReferenceProps(),
132
+ })}
133
+ </>
134
+ );
135
+ };
136
+
137
+ export const PopoverContent = ({ children, overlayCardProps }: { children: React.ReactNode, overlayCardProps: OverlayCardProps }) => {
138
+ const {
139
+ getFloatingProps,
140
+ isMounted,
141
+ refs,
142
+ floatingStyles,
143
+ transitionStyles,
144
+ } = useContext(PopoverContext);
145
+
146
+ if (!isMounted) {
147
+ return null;
148
+ }
149
+
150
+ return (
151
+ <FloatingPortal>
152
+ <Box
153
+ ref={refs.setFloating}
154
+ style={floatingStyles}
155
+ {...getFloatingProps()}
156
+ css={{
157
+ zIndex: "$overlayCard",
158
+ }}
159
+ >
160
+ <OverlayCard {...overlayCardProps} style={transitionStyles}>{children}</OverlayCard>
161
+ </Box>
162
+ </FloatingPortal>
163
+ );
164
+ };
@@ -0,0 +1,34 @@
1
+ import { useState } from "react";
2
+ import { Popover, PopoverContent, PopoverTrigger } from "./Popover";
3
+
4
+ export const Tooltip = ({ children, content }: {
5
+ children: React.ReactNode;
6
+ content: React.ReactNode
7
+ }) => {
8
+ const [open, setOpen] = useState(false);
9
+
10
+ return (
11
+ <Popover
12
+ open={open}
13
+ onOpenChange={setOpen}
14
+ trigger="hover"
15
+ placement="top"
16
+ offset={{ mainAxis: 8 }}
17
+ role="tooltip"
18
+ >
19
+ <PopoverTrigger>
20
+ {children}
21
+ </PopoverTrigger>
22
+ <PopoverContent overlayCardProps={{
23
+ css: {
24
+ background: "rgba(0,0,0, 0.9)",
25
+ color: "#fff",
26
+ fontSize: "$sm",
27
+ padding: "$1 $2"
28
+ }
29
+ }}>
30
+ {content}
31
+ </PopoverContent>
32
+ </Popover>
33
+ )
34
+ }
package/src/lib/ui/ui.ts CHANGED
@@ -2,4 +2,8 @@ export * from './stitches.config';
2
2
 
3
3
  export * from './components/Button';
4
4
  export * from './components/Spinner';
5
- export * from './components/Alert';
5
+ export * from './components/Alert';
6
+ export * from './components/OverlayCard';
7
+ export * from './components/Popover';
8
+ export * from './components/Box';
9
+ export * from './components/Tooltip';