@opsa-dev/ui-shared 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,13 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { createRoot } from 'react-dom/client';
3
+ export function OpsaLogo(props) {
4
+ return (_jsxs("div", { className: "Logo", children: [_jsx("div", { className: "left", children: "Opsa" }), _jsx("div", { className: "right", children: props.title })] }));
5
+ }
6
+ class OpsaLogoComponent extends HTMLElement {
7
+ connectedCallback() {
8
+ let shadow = this.attachShadow({ mode: 'open' });
9
+ shadow.adoptedStyleSheets = [];
10
+ createRoot(shadow).render(_jsx(OpsaLogo, { title: this.getAttribute('title') ?? '[Unknown]' }));
11
+ }
12
+ }
13
+ customElements.define("opsa-logo", OpsaLogoComponent);
@@ -0,0 +1,56 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { FloatingArrow, arrow, autoUpdate, flip, offset, shift, size, useDismiss, useFloating, useFocus, useHover, useInteractions, useRole } from '@floating-ui/react';
3
+ import { useEffect, useRef, useState } from 'react';
4
+ import { createPortal } from 'react-dom';
5
+ import { formatClass } from '@opsa-dev/ui-shared/scripts/utilities.js';
6
+ export function Tooltip(props) {
7
+ let [isOpen, setIsOpen] = useState(false);
8
+ let arrowRef = useRef(null);
9
+ let { refs, floatingStyles, context } = useFloating({
10
+ middleware: [
11
+ offset(6),
12
+ flip(),
13
+ shift({ padding: 5 }),
14
+ ...(props.arrow
15
+ ? [arrow({
16
+ element: arrowRef,
17
+ padding: 0,
18
+ })]
19
+ : []),
20
+ size({
21
+ padding: 5, // Same as in shift()
22
+ apply(state) {
23
+ let availableWidth = `${Math.max(0, state.availableWidth)}px`;
24
+ let availableHeight = `${Math.max(0, state.availableHeight)}px`;
25
+ state.elements.floating.style.setProperty('--available-width', availableWidth);
26
+ state.elements.floating.style.setProperty('--available-height', availableHeight);
27
+ },
28
+ }),
29
+ ],
30
+ onOpenChange: (open) => void setIsOpen(open && (!('enabled' in props) || !!props.enabled)),
31
+ open: isOpen,
32
+ placement: (props.placement ?? 'top'),
33
+ whileElementsMounted: autoUpdate,
34
+ });
35
+ let hover = useHover(context, { move: false });
36
+ let focus = useFocus(context);
37
+ let dismiss = useDismiss(context);
38
+ let role = useRole(context, { role: 'tooltip' });
39
+ let { getReferenceProps, getFloatingProps } = useInteractions([hover, focus, dismiss, role]);
40
+ useEffect(() => {
41
+ if (!props.enabled) {
42
+ setIsOpen(false);
43
+ }
44
+ }, [props.enabled]);
45
+ return (_jsxs(_Fragment, { children: [_jsx("div", { className: formatClass('TooltipTarget', { '_open': open }), ref: (el) => {
46
+ if (el) {
47
+ if (el.children.length !== 1) {
48
+ throw new Error('Tooltip must have exactly one child');
49
+ }
50
+ refs.setReference(el.children[0]);
51
+ }
52
+ else {
53
+ refs.setReference(null);
54
+ }
55
+ }, ...getReferenceProps(), children: props.children }), isOpen && createPortal((_jsxs("div", { className: "Tooltip", ref: refs.setFloating, style: floatingStyles, ...getFloatingProps(), children: [props.arrow && (_jsx(FloatingArrow, { className: "arrow", width: 10, height: 5, context: context, ref: arrowRef })), props.contents] })), document.body)] }));
56
+ }
@@ -0,0 +1,3 @@
1
+ export * from './components/logo.js';
2
+ export * from './components/tooltip.js';
3
+ export * from './utilities.js';
@@ -0,0 +1,19 @@
1
+ export function formatClass(...input) {
2
+ return input
3
+ .filter((item) => item)
4
+ .flatMap((item) => {
5
+ if (typeof item === 'string') {
6
+ return item;
7
+ }
8
+ if (Array.isArray(item)) {
9
+ return formatClass(...item);
10
+ }
11
+ if ((typeof item === 'object') && (item.constructor === Object)) {
12
+ return Object.entries(item)
13
+ .filter(([key, value]) => (key && value))
14
+ .map(([key, _value]) => key);
15
+ }
16
+ return [];
17
+ })
18
+ .join(' ');
19
+ }
@@ -0,0 +1,3 @@
1
+ export declare function OpsaLogo(props: {
2
+ title: string;
3
+ }): import("react").JSX.Element;
@@ -0,0 +1,8 @@
1
+ import { Placement } from '@floating-ui/react';
2
+ import { PropsWithChildren, ReactNode } from 'react';
3
+ export declare function Tooltip(props: PropsWithChildren<{
4
+ arrow: boolean;
5
+ contents: ReactNode;
6
+ enabled?: unknown;
7
+ placement?: Placement;
8
+ }>): import("react").JSX.Element;
@@ -0,0 +1,3 @@
1
+ export * from './components/logo.js';
2
+ export * from './components/tooltip.js';
3
+ export * from './utilities.js';
@@ -0,0 +1,2 @@
1
+ export type OrdinaryId = number | string;
2
+ export declare function formatClass(...input: (Record<string, unknown> | string | undefined)[]): string;
package/package.json ADDED
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "@opsa-dev/ui-shared",
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "main": "lib/scripts/index.js",
6
+ "types": "lib/types/index.d.ts",
7
+ "scripts": {
8
+ "build": "tsc"
9
+ },
10
+ "dependencies": {
11
+ "@floating-ui/react": "^0.27.19",
12
+ "@fontsource/finlandica-text": "^5.2.1",
13
+ "react": "19",
14
+ "react-dom": "19"
15
+ },
16
+ "devDependencies": {
17
+ "@slietar/tsconfig": "^1.0.0"
18
+ }
19
+ }
@@ -0,0 +1,30 @@
1
+ @import url("@fontsource/finlandica-text");
2
+
3
+
4
+ .Logo {
5
+ display: flex;
6
+ align-items: baseline;
7
+ column-gap: 6px;
8
+
9
+ font-family: "Finlandica Text";
10
+ font-size: 16px;
11
+ font-weight: 500;
12
+ line-height: 1.5;
13
+ text-transform: uppercase;
14
+
15
+ cursor: default;
16
+ user-select: none;
17
+
18
+ .left {
19
+ padding: 1px 8px;
20
+
21
+ background-color: #444342;
22
+ border-radius: 6px;
23
+
24
+ color: #fff;
25
+ }
26
+
27
+ .right {
28
+ color: #444342;
29
+ }
30
+ }
@@ -0,0 +1,2 @@
1
+ @import url("./reset.css") layer(reset);
2
+ @import url("./components/logo.css");
@@ -0,0 +1,184 @@
1
+ *, *::before, *::after {
2
+ box-sizing: inherit;
3
+ }
4
+
5
+ html {
6
+ box-sizing: border-box;
7
+ }
8
+
9
+ body {
10
+ margin: initial;
11
+ }
12
+
13
+ :focus {
14
+ outline: initial;
15
+ }
16
+
17
+ a {
18
+ display: block;
19
+
20
+ color: inherit;
21
+ text-decoration: initial;
22
+
23
+ &:focus {
24
+ outline: initial;
25
+ }
26
+ }
27
+
28
+ ul {
29
+ margin: initial;
30
+ padding: initial;
31
+ }
32
+
33
+ li {
34
+ display: block;
35
+ list-style-type: none;
36
+ }
37
+
38
+ h1, h2, h3, h4, h5, h6 {
39
+ margin: initial;
40
+ }
41
+
42
+ h1 {
43
+ /* Overrides user agent stylesheet such as section > h1. */
44
+ font-size: 2em;
45
+ }
46
+
47
+ p {
48
+ margin: initial;
49
+ }
50
+
51
+ input, button, select, textarea {
52
+ display: block;
53
+ inline-size: stretch;
54
+
55
+ margin: initial;
56
+ padding: initial;
57
+
58
+ appearance: none;
59
+ background: initial;
60
+ border: initial;
61
+ outline: initial;
62
+
63
+ color: inherit;
64
+ font: inherit;
65
+ text-align: initial;
66
+
67
+ &:disabled {
68
+ color: inherit;
69
+ opacity: initial;
70
+ }
71
+
72
+ &:active {
73
+ color: currentColor;
74
+ }
75
+ }
76
+
77
+ option {
78
+ padding: initial;
79
+ }
80
+
81
+ input::placeholder {
82
+ opacity: initial;
83
+ color: initial;
84
+ }
85
+
86
+ input[type="search"]::-webkit-search-decoration {
87
+ -webkit-appearance: none;
88
+ }
89
+
90
+ input[type="submit"], button {
91
+ &:not(:disabled) {
92
+ cursor: pointer;
93
+ }
94
+ }
95
+
96
+ output {
97
+ overflow: hidden;
98
+ text-overflow: ellipsis;
99
+ }
100
+
101
+ :invalid {
102
+ box-shadow: initial;
103
+ }
104
+
105
+ dialog {
106
+ max-width: unset;
107
+ max-height: unset;
108
+
109
+ margin: unset;
110
+ padding: unset;
111
+
112
+ background: transparent;
113
+ border: unset;
114
+
115
+ &::backdrop {
116
+ background: unset;
117
+ }
118
+ }
119
+
120
+ a, button {
121
+ -webkit-tap-highlight-color: transparent;
122
+ }
123
+
124
+ dl, dd {
125
+ margin: initial;
126
+ }
127
+
128
+ samp {
129
+ display: block;
130
+
131
+ margin: 1em 0;
132
+ }
133
+
134
+ label {
135
+ display: block;
136
+ }
137
+
138
+ img {
139
+ display: block;
140
+ max-width: 100%;
141
+ max-height: 100%;
142
+ }
143
+
144
+ table {
145
+ width: 100%;
146
+ border-spacing: initial;
147
+ }
148
+
149
+ th {
150
+ font-weight: initial;
151
+ text-align: initial;
152
+ }
153
+
154
+ tr, td {
155
+ padding: initial;
156
+ }
157
+
158
+ video {
159
+ display: block;
160
+ }
161
+
162
+ svg {
163
+ display: block;
164
+ /* width: 100%; */
165
+ height: intrinsic;
166
+ }
167
+
168
+ strong {
169
+ font-weight: unset;
170
+ }
171
+
172
+ iframe, object {
173
+ display: block;
174
+ width: 100%;
175
+ }
176
+
177
+ iframe {
178
+ height: 100%;
179
+ border: initial;
180
+ }
181
+
182
+ kbd {
183
+ font-family: inherit;
184
+ }