uibee 2.2.4 → 2.2.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/dist/globals.css CHANGED
@@ -57,6 +57,7 @@
57
57
  --color-login-800: #181818;
58
58
  --color-login-700: #1a1a1a;
59
59
  --color-login-600: #212121;
60
+ --color-login-500: #323232;
60
61
  --color-login-300: #5e5e5e;
61
62
  --color-login-200: #727272;
62
63
  --color-login-50: #ededed;
@@ -568,6 +569,9 @@
568
569
  .items-end {
569
570
  align-items: flex-end;
570
571
  }
572
+ .justify-between {
573
+ justify-content: space-between;
574
+ }
571
575
  .justify-center {
572
576
  justify-content: center;
573
577
  }
@@ -900,6 +904,9 @@
900
904
  color: color-mix(in oklab, var(--color-yellow-300) 70%, transparent);
901
905
  }
902
906
  }
907
+ .italic {
908
+ font-style: italic;
909
+ }
903
910
  .no-underline {
904
911
  text-decoration-line: none;
905
912
  }
@@ -1287,6 +1294,13 @@
1287
1294
  }
1288
1295
  }
1289
1296
  }
1297
+ .hover\:bg-login-500 {
1298
+ &:hover {
1299
+ @media (hover: hover) {
1300
+ background-color: var(--color-login-500);
1301
+ }
1302
+ }
1303
+ }
1290
1304
  .hover\:bg-login-600 {
1291
1305
  &:hover {
1292
1306
  @media (hover: hover) {
@@ -1,6 +1,7 @@
1
1
  export { default as Input } from './inputs/input';
2
2
  export { default as SwitchInput } from './inputs/switch';
3
3
  export { default as TagInput } from './inputs/tag';
4
+ export { default as Textarea } from './inputs/markdown';
4
5
  export { default as Logo } from './logo/logo';
5
6
  export { default as LogoSmall } from './logo/logoSmall';
6
7
  export { default as ThemeToggle } from './toggle/theme';
@@ -2,6 +2,7 @@
2
2
  export { default as Input } from './inputs/input';
3
3
  export { default as SwitchInput } from './inputs/switch';
4
4
  export { default as TagInput } from './inputs/tag';
5
+ export { default as Textarea } from './inputs/markdown';
5
6
  // Logos
6
7
  export { default as Logo } from './logo/logo';
7
8
  export { default as LogoSmall } from './logo/logoSmall';
@@ -0,0 +1,15 @@
1
+ type MarkdownProps = {
2
+ name: string;
3
+ label: string;
4
+ value: string;
5
+ setValue: (_: string | number) => void;
6
+ className?: string;
7
+ tooltip?: string;
8
+ required?: boolean;
9
+ rows?: number;
10
+ color?: string;
11
+ buttonColor?: string;
12
+ buttonColorHighlighted?: string;
13
+ };
14
+ export default function Markdown({ name, label, value, className, tooltip, required, rows, setValue, color, buttonColor, buttonColorHighlighted }: MarkdownProps): import("react/jsx-runtime").JSX.Element;
15
+ export {};
@@ -0,0 +1,32 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useRef, useState } from 'react';
4
+ import Label from './label';
5
+ import ToolTip from './tooltip';
6
+ export default function Markdown({ name, label, value, className, tooltip, required, rows = 6, setValue, color, buttonColor, buttonColorHighlighted }) {
7
+ const [hasBlured, setHasBlured] = useState(false);
8
+ const textareaRef = useRef(null);
9
+ const smallButtonStyle = `px-2 py-1 rounded
10
+ ${buttonColorHighlighted ? `hover:${buttonColorHighlighted}` : 'hover:bg-login-500'}
11
+ ${' '}${buttonColor ? buttonColor : 'bg-login-600'}`;
12
+ function wrapSelection(before, after = before, placeHolder = '') {
13
+ const textarea = textareaRef.current;
14
+ if (!textarea)
15
+ return;
16
+ const start = textarea.selectionStart;
17
+ const end = textarea.selectionEnd;
18
+ const selected = value.slice(start, end) || placeHolder;
19
+ const newValue = value.slice(0, start) + before + selected + after + value.slice(end);
20
+ setValue(newValue);
21
+ requestAnimationFrame(() => {
22
+ const pos = start + before.length;
23
+ textarea.focus();
24
+ textarea.setSelectionRange(pos, pos + selected.length);
25
+ });
26
+ }
27
+ return (_jsxs("div", { className: `w-full ${className ?? ''}`, children: [_jsxs("div", { className: 'relative', children: [_jsx("textarea", { name: name, ref: textareaRef, value: value, onChange: (e) => setValue(e.target.value), onBlur: () => setHasBlured(true), rows: rows, required: required, className: 'block px-2.5 pb-2.5 pt-4 w-full text-sm ' +
28
+ 'rounded-lg border-[0.10rem] appearance-none ' +
29
+ 'border-login-200 focus:outline-none focus:ring-0' +
30
+ ' focus:border-login-50 peer resize-vertical ' +
31
+ `${color ? color : 'bg-login-800'}` }), _jsx(Label, { label: label, value: value, color: color, required: required, showRequired: required && !value && hasBlured }), tooltip && _jsx(ToolTip, { info: tooltip })] }), _jsx("div", { className: 'flex items-center justify-between gap-2 mt-2', children: _jsxs("div", { className: 'flex gap-2', children: [_jsx("button", { type: 'button', className: smallButtonStyle, onClick: () => wrapSelection('**', '**', 'bold'), children: "B" }), _jsx("button", { type: 'button', className: smallButtonStyle, onClick: () => wrapSelection('*', '*', 'italic'), children: "I" }), _jsx("button", { type: 'button', className: smallButtonStyle, onClick: () => wrapSelection('\n```\n', '\n```\n', 'code block'), children: "CB" }), _jsx("button", { type: 'button', className: smallButtonStyle, onClick: () => wrapSelection('[', '](url)', 'text'), children: "Link" }), _jsx("button", { type: 'button', className: smallButtonStyle, onClick: () => wrapSelection('\n- ', '', 'list item'), children: "UL" })] }) })] }));
32
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "uibee",
3
- "version": "2.2.4",
3
+ "version": "2.2.5",
4
4
  "description": "Shared components, functions and hooks for reuse across Login projects",
5
5
  "homepage": "https://github.com/Login-Linjeforening-for-IT/uibee#readme",
6
6
  "bugs": {
@@ -2,6 +2,7 @@
2
2
  export { default as Input } from './inputs/input'
3
3
  export { default as SwitchInput } from './inputs/switch'
4
4
  export { default as TagInput } from './inputs/tag'
5
+ export { default as Textarea } from './inputs/markdown'
5
6
 
6
7
  // Logos
7
8
  export { default as Logo } from './logo/logo'
@@ -0,0 +1,129 @@
1
+ 'use client'
2
+
3
+ import { useRef, useState } from 'react'
4
+ import Label from './label'
5
+ import ToolTip from './tooltip'
6
+
7
+ type MarkdownProps = {
8
+ name: string
9
+ label: string
10
+ value: string
11
+ setValue: (_: string | number) => void
12
+ className?: string
13
+ tooltip?: string
14
+ required?: boolean
15
+ rows?: number
16
+ color?: string
17
+ buttonColor?: string
18
+ buttonColorHighlighted?: string
19
+ }
20
+
21
+ export default function Markdown({
22
+ name,
23
+ label,
24
+ value,
25
+ className,
26
+ tooltip,
27
+ required,
28
+ rows = 6,
29
+ setValue,
30
+ color,
31
+ buttonColor,
32
+ buttonColorHighlighted
33
+ }: MarkdownProps) {
34
+ const [hasBlured, setHasBlured] = useState(false)
35
+ const textareaRef = useRef<HTMLTextAreaElement | null>(null)
36
+ const smallButtonStyle = `px-2 py-1 rounded
37
+ ${buttonColorHighlighted ? `hover:${buttonColorHighlighted}` : 'hover:bg-login-500'}
38
+ ${' '}${buttonColor ? buttonColor : 'bg-login-600'}`
39
+
40
+ function wrapSelection(before: string, after = before, placeHolder = '') {
41
+ const textarea = textareaRef.current
42
+ if (!textarea) return
43
+ const start = textarea.selectionStart
44
+ const end = textarea.selectionEnd
45
+ const selected = value.slice(start, end) || placeHolder
46
+ const newValue =
47
+ value.slice(0, start) + before + selected + after + value.slice(end)
48
+ setValue(newValue)
49
+ requestAnimationFrame(() => {
50
+ const pos = start + before.length
51
+ textarea.focus()
52
+ textarea.setSelectionRange(pos, pos + selected.length)
53
+ })
54
+ }
55
+
56
+ return (
57
+ <div className={`w-full ${className ?? ''}`}>
58
+ <div className='relative'>
59
+ <textarea
60
+ name={name}
61
+ ref={textareaRef}
62
+ value={value}
63
+ onChange={(e) => setValue(e.target.value)}
64
+ onBlur={() => setHasBlured(true)}
65
+ rows={rows}
66
+ required={required}
67
+ className={
68
+ 'block px-2.5 pb-2.5 pt-4 w-full text-sm ' +
69
+ 'rounded-lg border-[0.10rem] appearance-none ' +
70
+ 'border-login-200 focus:outline-none focus:ring-0' +
71
+ ' focus:border-login-50 peer resize-vertical ' +
72
+ `${color ? color : 'bg-login-800'}`
73
+ }
74
+ />
75
+
76
+ <Label
77
+ label={label}
78
+ value={value}
79
+ color={color}
80
+ required={required}
81
+ showRequired={required && !value && hasBlured}
82
+ />
83
+ {tooltip && <ToolTip info={tooltip} />}
84
+ </div>
85
+
86
+ <div className='flex items-center justify-between gap-2 mt-2'>
87
+ <div className='flex gap-2'>
88
+ <button
89
+ type='button'
90
+ className={smallButtonStyle}
91
+ onClick={() => wrapSelection('**', '**', 'bold')}
92
+ >
93
+ B
94
+ </button>
95
+ <button
96
+ type='button'
97
+ className={smallButtonStyle}
98
+ onClick={() => wrapSelection('*', '*', 'italic')}
99
+ >
100
+ I
101
+ </button>
102
+ <button
103
+ type='button'
104
+ className={smallButtonStyle}
105
+ onClick={() =>
106
+ wrapSelection('\n```\n', '\n```\n', 'code block')
107
+ }
108
+ >
109
+ CB
110
+ </button>
111
+ <button
112
+ type='button'
113
+ className={smallButtonStyle}
114
+ onClick={() => wrapSelection('[', '](url)', 'text')}
115
+ >
116
+ Link
117
+ </button>
118
+ <button
119
+ type='button'
120
+ className={smallButtonStyle}
121
+ onClick={() => wrapSelection('\n- ', '', 'list item')}
122
+ >
123
+ UL
124
+ </button>
125
+ </div>
126
+ </div>
127
+ </div>
128
+ )
129
+ }