Skip to content

Commit

Permalink
refactor: 💡 Use options object instead of area strings
Browse files Browse the repository at this point in the history
To be able to steer the API towards a decent interface for programmatic
usage and other frameworks, the settings and features enabled are to be
governed by passed options instead of strings.

BREAKING CHANGE: 🧨 Have changed the API to accept an option object instead of a string.
Please check the documentation.
  • Loading branch information
phun-ky committed Aug 28, 2024
1 parent 8ba8591 commit 3560dda
Show file tree
Hide file tree
Showing 18 changed files with 500 additions and 284 deletions.
31 changes: 14 additions & 17 deletions src/features/grid/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/* eslint no-console:0 */
import { isValidGridElement } from '../../utils/area';
import { SpeccerOptionsInterface } from '../../types/speccer';
import { SPECCER_DATA_ATTRIBUTE } from '../../utils/constants';
import { getOptions } from '../../utils/get-options';
import { isElementHidden } from '../../utils/node';
import { offset } from '../../utils/position';
import { get as getStyles } from '../../utils/styles';
Expand All @@ -26,11 +27,15 @@ import { waitForFrame } from '../../utils/wait';
export const create = async (
targetElement: HTMLElement,
styles: CSSStyleDeclaration,
options: Record<string, string>
options: SpeccerOptionsInterface
): Promise<void> => {
await waitForFrame();

const { toggle } = options;
const { grid } = options;

if (!grid) return;

const { toggle } = grid;
const { height, width } = targetElement.getBoundingClientRect();
const { top, left } = await offset(targetElement);
const { gridTemplateColumns, gridTemplateRows, padding } = styles;
Expand Down Expand Up @@ -137,24 +142,16 @@ export const create = async (
export const element = async (targetElement: HTMLElement): Promise<void> => {
if (!targetElement) return;

const _areas_string: string | null = targetElement.getAttribute(
SPECCER_DATA_ATTRIBUTE
);
const _target_styles = await getStyles(targetElement);
const _areas_string: string =
targetElement.getAttribute(SPECCER_DATA_ATTRIBUTE) || '';
const _target_style = await getStyles(targetElement);
const _options = getOptions(_areas_string, _target_style);

if (!isValidGridElement(_areas_string, _target_styles)) return;
if (_options.type !== 'grid' || !_options.grid) return;

if (isElementHidden(targetElement)) return;

await waitForFrame();

const options = {
toggle: 'both'
};

if (_areas_string?.includes('columns')) options.toggle = 'columns';

if (_areas_string?.includes('rows')) options.toggle = 'rows';

await create(targetElement, _target_styles, options);
await create(targetElement, _target_style, _options);
};
14 changes: 9 additions & 5 deletions src/features/mark/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
/* eslint no-console:0 */
import { isValidMarkElement } from '../../utils/area';
import { cx, set } from '../../utils/classnames';
import { SPECCER_DATA_ATTRIBUTE } from '../../utils/constants';
import { getOptions } from '../../utils/get-options';
import { isElementHidden } from '../../utils/node';
import { getRec } from '../../utils/position';
import { add as addStyles } from '../../utils/styles';
import { waitForFrame } from '../../utils/wait';

/**
* Create a marker element with an optional element type.
Expand Down Expand Up @@ -44,11 +45,14 @@ export const create = (n = 'span'): HTMLElement => {
export const element = async (targetElement: HTMLElement): Promise<void> => {
if (!targetElement) return;

const _areas_string: string | null = targetElement.getAttribute(
SPECCER_DATA_ATTRIBUTE
);
const _areas_string: string =
targetElement.getAttribute(SPECCER_DATA_ATTRIBUTE) || '';

if (!isValidMarkElement(_areas_string)) return;
await waitForFrame();

const _options = getOptions(_areas_string, getComputedStyle(targetElement));

if (_options.type !== 'mark') return;

if (isElementHidden(targetElement)) return;

Expand Down
77 changes: 42 additions & 35 deletions src/features/measure/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
/* eslint no-console:0 */
import { MeasureAreaEnum } from '../../types/enums/area';
import {
isBottomArea,
isHeightArea,
isRightArea,
isValidMeasureElement,
isWidthArea
} from '../../utils/area';
import { set as setClassNames } from '../../utils/classnames';
import { SpeccerOptionsInterface } from '../../types/speccer';
import { cx, set as setClassNames } from '../../utils/classnames';
import { getOptions } from '../../utils/get-options';
import { isElementHidden } from '../../utils/node';
import { getRec } from '../../utils/position';
import { add as addStyles } from '../../utils/styles';
Expand All @@ -17,7 +12,7 @@ import { waitForFrame } from '../../utils/wait';
* Create a measurement element with optional text, area, and element type.
*
* @param {string | number} text - The text to display on the element.
* @param {string | null} area - The area to specify with CSS class.
* @param {SpeccerOptionsInterface} options - The options.
* @param {string} tag - The element type.
* @returns {HTMLElement} - The created measurement element.
*
Expand All @@ -29,15 +24,23 @@ import { waitForFrame } from '../../utils/wait';
*/
export const create = (
text: string | number = '',
area: string | null = '',
options: SpeccerOptionsInterface,
tag = 'span'
): HTMLElement => {
const _el = document.createElement(tag);

_el.setAttribute('title', `${text}px`);
_el.setAttribute('data-measure', `${parseInt(String(text), 10)}px`);

setClassNames(_el, `ph-speccer speccer measure ${area}`);
const { measure, position } = options;
const _class_names = cx('ph-speccer speccer measure', {
height: measure?.height || false,
width: measure?.width || false,
slim: measure?.slim || false,
[position]: true
});

setClassNames(_el, _class_names);

return _el;
};
Expand All @@ -59,29 +62,33 @@ export const create = (
export const element = async (targetElement: HTMLElement): Promise<void> => {
if (!targetElement) return;

const _areas_string: string | null =
targetElement.getAttribute('data-speccer');
const _areas_string: string =
targetElement.getAttribute('data-speccer') || '';

await waitForFrame();

const _options = getOptions(_areas_string, getComputedStyle(targetElement));

if (!isValidMeasureElement(_areas_string)) return;
if (_options.type !== 'measure' || !_options.measure) return;

if (isElementHidden(targetElement)) return;

await waitForFrame();

const isSlim = _areas_string?.includes(MeasureAreaEnum.Slim);
const { measure, position } = _options;
const _target_rect = targetElement.getBoundingClientRect();
const widthModifier = !isSlim ? 48 : 0;
const heightModifier = !isSlim ? 96 : 0;
const _width_modifier = !measure.slim ? 48 : 0;
const _height_modifier = !measure.slim ? 96 : 0;

if (isWidthArea(_areas_string)) {
if (isBottomArea(_areas_string)) {
const _measure_el = create(_target_rect.width, _areas_string);
if (measure.width) {
if (position === MeasureAreaEnum.Bottom) {
const _measure_el = create(_target_rect.width, _options);

document.body.appendChild(_measure_el);

const _positional_styles = await getRec(_measure_el, targetElement);

if (isSlim) {
if (measure.slim) {
const { left, top, width } = _positional_styles.fromBottom({
center: false
});
Expand All @@ -100,17 +107,17 @@ export const element = async (targetElement: HTMLElement): Promise<void> => {
left: `${left}px`,
top: `${top}px`,
width: `${width}px`,
height: `${height + widthModifier}px`
height: `${height + _width_modifier}px`
});
}
} else {
const _measure_el = create(_target_rect.width, _areas_string);
const _measure_el = create(_target_rect.width, _options);

document.body.appendChild(_measure_el);

const _positional_styles = await getRec(_measure_el, targetElement);

if (isSlim) {
if (measure.slim) {
const { left, top, width } = _positional_styles.fromTop({
center: false
});
Expand All @@ -127,21 +134,21 @@ export const element = async (targetElement: HTMLElement): Promise<void> => {

await addStyles(_measure_el, {
left: `${left}px`,
top: `${top - widthModifier}px`,
top: `${top - _width_modifier}px`,
width: `${width}px`,
height: `${height + widthModifier}px`
height: `${height + _width_modifier}px`
});
}
}
} else if (isHeightArea(_areas_string)) {
if (isRightArea(_areas_string)) {
const _measure_el = create(_target_rect.height, _areas_string);
} else if (measure.height) {
if (position === MeasureAreaEnum.Right) {
const _measure_el = create(_target_rect.height, _options);

document.body.appendChild(_measure_el);

const _positional_styles = await getRec(_measure_el, targetElement);

if (isSlim) {
if (measure.slim) {
const { left, top, height } = _positional_styles.fromRight({
center: false
});
Expand All @@ -160,17 +167,17 @@ export const element = async (targetElement: HTMLElement): Promise<void> => {
left: `${left}px`,
top: `${top}px`,
height: `${height}px`,
width: `${width + heightModifier}px`
width: `${width + _height_modifier}px`
});
}
} else {
const _measure_el = create(_target_rect.height, _areas_string);
const _measure_el = create(_target_rect.height, _options);

document.body.appendChild(_measure_el);

const _positional_styles = await getRec(_measure_el, targetElement);

if (isSlim) {
if (measure.slim) {
const { left, top, height } = _positional_styles.fromLeft({
center: false
});
Expand All @@ -186,10 +193,10 @@ export const element = async (targetElement: HTMLElement): Promise<void> => {
});

await addStyles(_measure_el, {
left: `${left - heightModifier}px`,
left: `${left - _height_modifier}px`,
top: `${top}px`,
height: `${height}px`,
width: `${width + heightModifier}px`
width: `${width + _height_modifier}px`
});
}
}
Expand Down
17 changes: 12 additions & 5 deletions src/features/pin/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,12 @@ export { createPinElement } from './utils/create-pin-element';
export { pinElement } from './utils/pin-element';

import { SPECCER_LITERALS } from '../../utils/constants';
import { getOptions } from '../../utils/get-options';
import { isElementHidden } from '../../utils/node';
import { waitForFrame } from '../../utils/wait';

import { getCharacterToUse } from './utils/get-character-to-use';
import { getContentForPin } from './utils/get-content-for-pin';
import { pinElement } from './utils/pin-element';

/**
Expand Down Expand Up @@ -66,12 +69,16 @@ export const pinElements = async (
targetElement: HTMLElement,
targetIndex: number
): Promise<void> => {
const _character_to_use = getCharacterToUse(
targetIndex,
_literals_to_use
);
const _symbol = getCharacterToUse(targetIndex, _literals_to_use);
const _areas_string = targetElement.getAttribute('data-speccer') || '';

await pinElement(targetElement, _character_to_use, sectionElement);
await waitForFrame();

const _target_style = getComputedStyle(targetElement);
const _options = getOptions(_areas_string, _target_style);
const _content = getContentForPin(_symbol, targetElement, _options);

await pinElement(targetElement, sectionElement, _content, _options);
}
);
};
Loading

0 comments on commit 3560dda

Please sign in to comment.