UNPKG

10 kBJavaScriptView Raw
1/*!
2 * The Sutton SignWriting Web Components
3 */
4import { c as createCommonjsModule, a as commonjsGlobal } from './_commonjsHelpers-383fba37.js';
5
6var style = createCommonjsModule(function (module, exports) {
7/**
8* Sutton SignWriting Core Module v1.5.4 (https://github.com/sutton-signwriting/core)
9* Author: Steve Slevinski (https://SteveSlevinski.me)
10* style.js is released under the MIT License.
11*/
12
13(function (global, factory) {
14 factory(exports) ;
15})(commonjsGlobal, (function (exports) {
16 /**
17 * Object of regular expressions for style strings
18 *
19 * @alias style.re
20 * @type {object}
21 * @property {string} colorize - regular expression for colorize section
22 * @property {string} colorhex - regular expression for color hex values with 3 or 6 characters
23 * @property {string} colorname - regular expression for css color name
24 * @property {string} padding - regular expression for padding section
25 * @property {string} zoom - regular expression for zoom section
26 * @property {string} classbase - regular expression for class name definition
27 * @property {string} id - regular expression for id definition
28 * @property {string} colorbase - regular expression for color hex or color name
29 * @property {string} color - regular expression for single color entry
30 * @property {string} colors - regular expression for double color entry
31 * @property {string} background - regular expression for background section
32 * @property {string} detail - regular expression for color details for line and optional fill
33 * @property {string} detailsym - regular expression for color details for individual symbols
34 * @property {string} classes - regular expression for one or more class names
35 * @property {string} full - full regular expression for style string
36 */
37 let re = {
38 'colorize': 'C',
39 'colorhex': '(?:[0-9a-fA-F]{3}){1,2}',
40 'colorname': '[a-zA-Z]+',
41 'padding': 'P[0-9]{2}',
42 'zoom': 'Z(?:[0-9]+(?:\\.[0-9]+)?|x)',
43 'classbase': '-?[_a-zA-Z][_a-zA-Z0-9-]{0,100}',
44 'id': '[a-zA-Z][_a-zA-Z0-9-]{0,100}'
45 };
46 re.colorbase = `(?:${re.colorhex}|${re.colorname})`;
47 re.color = `_${re.colorbase}_`;
48 re.colors = `_${re.colorbase}(?:,${re.colorbase})?_`;
49 re.background = `G${re.color}`;
50 re.detail = `D${re.colors}`;
51 re.detailsym = `D[0-9]{2}${re.colors}`;
52 re.classes = `${re.classbase}(?: ${re.classbase})*`;
53 re.full = `-(${re.colorize})?(${re.padding})?(${re.background})?(${re.detail})?(${re.zoom})?(?:-((?:${re.detailsym})*))?(?:-(${re.classes})?!(?:(${re.id})!)?)?`;
54
55 const prefixColor = color => {
56 const regex = new RegExp(`^${re.colorhex}$`);
57 return (regex.test(color) ? '#' : '') + color;
58 };
59
60 const definedProps = obj => Object.fromEntries(Object.entries(obj).filter(([k, v]) => v !== undefined));
61 /**
62 * Function to parse style string to object
63 * @function style.parse
64 * @param {string} styleString - a style string
65 * @returns {StyleObject} elements of style string
66 * @example
67 * style.parse('-CP10G_blue_D_red,Cyan_')
68 *
69 * return {
70 * 'colorize': true,
71 * 'padding': 10,
72 * 'background': 'blue',
73 * 'detail': ['red', 'Cyan']
74 * }
75 */
76
77
78 const parse = styleString => {
79 const regex = `^${re.full}`;
80 const m = (typeof styleString === 'string' ? styleString.match(new RegExp(regex)) : []) || [];
81 return definedProps({
82 'colorize': !m[1] ? undefined : !!m[1],
83 'padding': !m[2] ? undefined : parseInt(m[2].slice(1)),
84 'background': !m[3] ? undefined : prefixColor(m[3].slice(2, -1)),
85 'detail': !m[4] ? undefined : m[4].slice(2, -1).split(',').map(prefixColor),
86 'zoom': !m[5] ? undefined : m[5] === 'Zx' ? 'x' : parseFloat(m[5].slice(1)),
87 'detailsym': !m[6] ? undefined : m[6].match(new RegExp(re.detailsym, 'g')).map(val => {
88 const parts = val.split('_');
89 const detail = parts[1].split(',').map(prefixColor);
90 return {
91 'index': parseInt(parts[0].slice(1)),
92 'detail': detail
93 };
94 }),
95 'classes': !m[7] ? undefined : m[7],
96 'id': !m[8] ? undefined : m[8]
97 });
98 };
99
100 /**
101 * Function to compose style string from object
102 * @function style.compose
103 * @param {StyleObject} styleObject - an object of style options
104 * @returns {string} style string
105 * @example
106 * style.compose({
107 * 'colorize': true,
108 * 'padding': 10,
109 * 'background': 'blue',
110 * 'detail': ['red', 'Cyan'],
111 * 'zoom': 1.1,
112 * 'detailsym': [
113 * {
114 * 'index': 1,
115 * 'detail': ['#ff00ff']
116 * },
117 * {
118 * 'index': 2,
119 * 'detail': ['yellow', 'green']
120 * }
121 * ],
122 * 'classes': 'primary blinking',
123 * 'id': 'cursor'
124 * })
125 *
126 * return '-CP10G_blue_D_red,Cyan_Z1.1-D01_ff00ff_D02_yellow,green_-primary blinking!cursor!'
127 */
128
129 const compose = styleObject => {
130 if (typeof styleObject !== 'object' || styleObject === null) return undefined; // three sections
131
132 let style1 = '-';
133 style1 += !styleObject.colorize ? '' : 'C';
134 const padding = parseInt(styleObject.padding);
135 style1 += !padding || padding <= 0 || padding > 99 ? '' : 'P' + (padding > 9 ? padding : '0' + padding);
136 const background = !styleObject.background || !(typeof styleObject.background === 'string') ? undefined : styleObject.background.match(re.colorbase)[0];
137 style1 += !background ? '' : 'G_' + background + '_';
138 const detail1 = !styleObject.detail || !styleObject.detail[0] || !(typeof styleObject.detail[0] === 'string') ? undefined : styleObject.detail[0].match(re.colorbase)[0];
139 const detail2 = !styleObject.detail || !styleObject.detail[1] || !(typeof styleObject.detail[1] === 'string') ? undefined : styleObject.detail[1].match(re.colorbase)[0];
140
141 if (detail1) {
142 style1 += 'D_' + detail1;
143
144 if (detail2) {
145 style1 += ',' + detail2;
146 }
147
148 style1 += '_';
149 }
150
151 const zoom = styleObject.zoom === 'x' ? 'x' : parseFloat(styleObject.zoom);
152 style1 += !zoom || zoom <= 0 ? '' : 'Z' + zoom;
153 let style2 = '';
154 const detailsym = !styleObject.detailsym || !Array.isArray(styleObject.detailsym) ? [] : styleObject.detailsym.map(styleObject => {
155 const index = parseInt(styleObject.index);
156 if (!index || index <= 0 || index > 99) return '';
157 let style = 'D' + (index > 9 ? index : '0' + index);
158 const detail1 = !styleObject.detail || !styleObject.detail[0] ? undefined : styleObject.detail[0].match(re.colorbase)[0];
159 const detail2 = !styleObject.detail || !styleObject.detail[1] ? undefined : styleObject.detail[1].match(re.colorbase)[0];
160
161 if (detail1) {
162 style += '_' + detail1;
163
164 if (detail2) {
165 style += ',' + detail2;
166 }
167
168 style += '_';
169 }
170
171 return style;
172 });
173 style2 += detailsym.join('');
174 let style3 = '';
175 const classes = !styleObject.classes || !(typeof styleObject.classes === 'string') ? undefined : styleObject.classes.match(re.classes)[0];
176 style3 += !classes ? '' : classes;
177 const id = !styleObject.id || !(typeof styleObject.id === 'string') ? undefined : styleObject.id.match(re.id)[0];
178 style3 += classes || id ? '!' : '';
179 style3 += !id ? '' : id + '!';
180 return style1 + (style2 || style3 ? '-' + style2 : '') + (style3 ? '-' + style3 : '');
181 };
182
183 /**
184 * Function to merge style objects
185 * @function style.merge
186 * @param {StyleObject} style1 - a style object
187 * @param {StyleObject} style2 - a style object
188 * @returns {StyleObject} a style object
189 * @example
190 * style.merge({'colorize': true},{zoom:2})
191 *
192 * return {
193 * 'colorize': true,
194 * 'zoom': 2
195 * }
196 */
197 const merge = (style1, style2) => {
198 if (typeof style1 !== 'object') style1 = {};
199 if (typeof style2 !== 'object') style2 = {};
200 const zoom1 = 'zoom' in style1 ? style1['zoom'] : 1;
201 const zoom2 = 'zoom' in style2 ? style2['zoom'] : 1;
202 return { ...style1,
203 ...style2,
204 ...{
205 zoom: zoom1 * zoom2
206 }
207 };
208 };
209
210 const rgb2arr = rgb => {
211 if (typeof rgb !== 'string') return [0, 0, 0];
212 return rgb.replace(/rgba?\((.+?)\)/ig, (_, values) => {
213 return values;
214 }).split(',').map(Number);
215 };
216
217 const arr2hex = arr => {
218 return arr.slice(0, 3).map(num => num.toString(16).padStart(2, '0')).join('');
219 };
220 /**
221 * Function to convert rgb color to hex or "transparent" if below tolerance
222 * @function style.rgb2hex
223 * @param {string} rgb - an rgb color
224 * @param {number} [tolerance=0] - max alpha for full transparency
225 * @returns {string} a hex color or "transparent"
226 * @example
227 * style.rgb2hex("rgb(255,255,255)")
228 * return "ffffff"
229 *
230 * style.rgb2hex("rgba(255,255,255,0.5)",0.5)
231 * return "transparent"
232 */
233
234
235 const rgb2hex = (rgb, tolerance = 0) => {
236 const arr = rgb2arr(rgb);
237
238 if (arr.length == 4 && arr[3] <= tolerance) {
239 return 'transparent';
240 } else {
241 return arr2hex(arr);
242 }
243 };
244 /**
245 * Function to merge color with background based on alpha transparency
246 * @function style.rgba2hex
247 * @param {string} color - an rgba color
248 * @param {string} background - an rgba background color
249 * @returns {string} a hex color or "transparent"
250 * @example
251 * style.rgba2hex("rgba(255,255,255,0.5)","rgb(0,0,0)")
252 *
253 * return "7f7f7f"
254 */
255
256
257 const rgba2hex = (color, background) => {
258 const bArr = rgb2arr(background);
259 const cArr = rgb2arr(color);
260 const alpha = cArr.length == 4 ? cArr[3] : 1;
261
262 if (alpha == 0) {
263 return 'transparent';
264 } else {
265 return arr2hex(cArr.map((v, i) => parseInt((1 - alpha) * bArr[i] + alpha * v)));
266 }
267 };
268
269 exports.compose = compose;
270 exports.merge = merge;
271 exports.parse = parse;
272 exports.re = re;
273 exports.rgb2hex = rgb2hex;
274 exports.rgba2hex = rgba2hex;
275
276 Object.defineProperty(exports, '__esModule', { value: true });
277
278}));
279
280/* support ongoing development on https://patreon.com/signwriting */
281});
282
283export { style as s };