@pindoba/core-attachment 0.0.0-alpha-20260426220647
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/LICENSE +12 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +4 -0
- package/dist/src/connect-attachment.d.ts +19 -0
- package/dist/src/connect-attachment.d.ts.map +1 -0
- package/dist/src/connect-attachment.js +55 -0
- package/dist/src/connect-attachment.js.map +1 -0
- package/dist/src/create-attachment.d.ts +7 -0
- package/dist/src/create-attachment.d.ts.map +1 -0
- package/dist/src/create-attachment.js +142 -0
- package/dist/src/create-attachment.js.map +1 -0
- package/dist/src/position-styles.d.ts +8 -0
- package/dist/src/position-styles.d.ts.map +1 -0
- package/dist/src/position-styles.js +20 -0
- package/dist/src/position-styles.js.map +1 -0
- package/dist/src/types.d.ts +112 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +1 -0
- package/package.json +37 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
Copyright 2025 Eduardo Lopes
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
4
|
+
|
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
6
|
+
|
|
7
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
|
8
|
+
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
|
9
|
+
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
|
|
10
|
+
FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
11
|
+
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
12
|
+
DEALINGS IN THE SOFTWARE.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { AttachmentAnchor, AttachmentApi, AttachmentBaseProps, AttachmentClasses, AttachmentConfig, AttachmentContentProps, AttachmentPassThrough, AttachmentRootProps, AttachmentShape, AttachmentSlotPassThrough, ConnectAttachmentOptions, ElementAttributes, HeadlessAttachment, Placement, PositionState } from "./src/types.js";
|
|
2
|
+
import { attachmentDefaults, connectAttachment } from "./src/connect-attachment.js";
|
|
3
|
+
import { createAttachment } from "./src/create-attachment.js";
|
|
4
|
+
import { getAttachmentPositionStyleString, getAttachmentPositionStyles } from "./src/position-styles.js";
|
|
5
|
+
export { type AttachmentAnchor, type AttachmentApi, type AttachmentBaseProps, type AttachmentClasses, type AttachmentConfig, type AttachmentContentProps, type AttachmentPassThrough, type AttachmentRootProps, type AttachmentShape, type AttachmentSlotPassThrough, type ConnectAttachmentOptions, type ElementAttributes, type HeadlessAttachment, type Placement, type PositionState, attachmentDefaults, connectAttachment, createAttachment, getAttachmentPositionStyleString, getAttachmentPositionStyles };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { attachmentDefaults, connectAttachment } from "./src/connect-attachment.js";
|
|
2
|
+
import { getAttachmentPositionStyleString, getAttachmentPositionStyles } from "./src/position-styles.js";
|
|
3
|
+
import { createAttachment } from "./src/create-attachment.js";
|
|
4
|
+
export { attachmentDefaults, connectAttachment, createAttachment, getAttachmentPositionStyleString, getAttachmentPositionStyles };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { AttachmentApi, ConnectAttachmentOptions } from "./types.js";
|
|
2
|
+
|
|
3
|
+
//#region src/connect-attachment.d.ts
|
|
4
|
+
declare const attachmentDefaults: {
|
|
5
|
+
readonly placement: "top-end";
|
|
6
|
+
readonly anchor: "corner";
|
|
7
|
+
readonly shape: "rect";
|
|
8
|
+
readonly hugCorners: false;
|
|
9
|
+
readonly offset: 0;
|
|
10
|
+
readonly offsetX: 0;
|
|
11
|
+
readonly offsetY: 0;
|
|
12
|
+
readonly flip: false;
|
|
13
|
+
readonly shift: false;
|
|
14
|
+
readonly padding: 0;
|
|
15
|
+
};
|
|
16
|
+
declare function connectAttachment(options?: ConnectAttachmentOptions): AttachmentApi;
|
|
17
|
+
//#endregion
|
|
18
|
+
export { attachmentDefaults, connectAttachment };
|
|
19
|
+
//# sourceMappingURL=connect-attachment.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connect-attachment.d.ts","names":[],"sources":["../../src/connect-attachment.ts"],"mappings":";;;cAQa,kBAAA;EAAA;;;;;;;;;;;iBA+BG,iBAAA,CACd,OAAA,GAAS,wBAAA,GACR,aAAA"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { css } from "@pindoba/styled-system/css";
|
|
2
|
+
import { attachmentStyles } from "@pindoba/styles-attachment";
|
|
3
|
+
//#region src/connect-attachment.ts
|
|
4
|
+
const attachmentDefaults = {
|
|
5
|
+
placement: "top-end",
|
|
6
|
+
anchor: "corner",
|
|
7
|
+
shape: "rect",
|
|
8
|
+
hugCorners: false,
|
|
9
|
+
offset: 0,
|
|
10
|
+
offsetX: 0,
|
|
11
|
+
offsetY: 0,
|
|
12
|
+
flip: false,
|
|
13
|
+
shift: false,
|
|
14
|
+
padding: 0
|
|
15
|
+
};
|
|
16
|
+
const classes = attachmentStyles.raw();
|
|
17
|
+
function connectAttachment(options = {}) {
|
|
18
|
+
const { placement = attachmentDefaults.placement, anchor = attachmentDefaults.anchor, shape = attachmentDefaults.shape, hugCorners = attachmentDefaults.hugCorners, offset = attachmentDefaults.offset, offsetX = attachmentDefaults.offsetX, offsetY = attachmentDefaults.offsetY, padding = attachmentDefaults.padding, passThrough, class: className } = options;
|
|
19
|
+
const flip = options.flip ?? anchor === "outside";
|
|
20
|
+
const shift = options.shift ?? anchor === "outside";
|
|
21
|
+
const rootClass = css(classes.root, passThrough?.root?.style, className);
|
|
22
|
+
const contentClass = css(classes.content, passThrough?.content?.style);
|
|
23
|
+
return {
|
|
24
|
+
rootProps: {
|
|
25
|
+
"data-component": "attachment",
|
|
26
|
+
...passThrough?.root?.props,
|
|
27
|
+
class: rootClass
|
|
28
|
+
},
|
|
29
|
+
contentProps: {
|
|
30
|
+
"data-component": "attachment-content",
|
|
31
|
+
...passThrough?.content?.props,
|
|
32
|
+
class: contentClass
|
|
33
|
+
},
|
|
34
|
+
classes: {
|
|
35
|
+
root: rootClass,
|
|
36
|
+
content: contentClass
|
|
37
|
+
},
|
|
38
|
+
config: {
|
|
39
|
+
placement,
|
|
40
|
+
anchor,
|
|
41
|
+
shape,
|
|
42
|
+
hugCorners,
|
|
43
|
+
offset,
|
|
44
|
+
offsetX,
|
|
45
|
+
offsetY,
|
|
46
|
+
flip,
|
|
47
|
+
shift,
|
|
48
|
+
padding
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
//#endregion
|
|
53
|
+
export { attachmentDefaults, connectAttachment };
|
|
54
|
+
|
|
55
|
+
//# sourceMappingURL=connect-attachment.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connect-attachment.js","names":[],"sources":["../../src/connect-attachment.ts"],"sourcesContent":["import { css } from \"@pindoba/styled-system/css\";\nimport { attachmentStyles } from \"@pindoba/styles-attachment\";\nimport type {\n AttachmentApi,\n ConnectAttachmentOptions,\n AttachmentConfig,\n} from \"./types.js\";\n\nexport const attachmentDefaults = {\n placement: \"top-end\",\n anchor: \"corner\",\n shape: \"rect\",\n hugCorners: false,\n offset: 0,\n offsetX: 0,\n offsetY: 0,\n // flip/shift default to false for \"corner\" (intentional placement) and true\n // for \"outside\" (popover-like). Resolved per-call in connectAttachment.\n flip: false,\n shift: false,\n padding: 0,\n} as const satisfies Required<\n Pick<\n AttachmentConfig,\n | \"placement\"\n | \"anchor\"\n | \"shape\"\n | \"hugCorners\"\n | \"offset\"\n | \"offsetX\"\n | \"offsetY\"\n | \"flip\"\n | \"shift\"\n | \"padding\"\n >\n>;\n\nconst classes = attachmentStyles.raw();\n\nexport function connectAttachment(\n options: ConnectAttachmentOptions = {},\n): AttachmentApi {\n const {\n placement = attachmentDefaults.placement,\n anchor = attachmentDefaults.anchor,\n shape = attachmentDefaults.shape,\n hugCorners = attachmentDefaults.hugCorners,\n offset = attachmentDefaults.offset,\n offsetX = attachmentDefaults.offsetX,\n offsetY = attachmentDefaults.offsetY,\n padding = attachmentDefaults.padding,\n passThrough,\n class: className,\n } = options;\n\n // Corner anchoring is an intentional placement (badges, status dots, stamps)\n // — flipping/shifting would silently move the indicator to a different corner\n // when space is tight, which is jarring. Outside anchoring is popover-like\n // and benefits from staying inside the viewport, so it keeps flip/shift on.\n const flip = options.flip ?? anchor === \"outside\";\n const shift = options.shift ?? anchor === \"outside\";\n\n const rootClass = css(classes.root, passThrough?.root?.style, className);\n const contentClass = css(classes.content, passThrough?.content?.style);\n\n return {\n rootProps: {\n \"data-component\": \"attachment\",\n ...passThrough?.root?.props,\n class: rootClass,\n },\n contentProps: {\n \"data-component\": \"attachment-content\",\n ...passThrough?.content?.props,\n class: contentClass,\n },\n classes: {\n root: rootClass,\n content: contentClass,\n },\n config: {\n placement,\n anchor,\n shape,\n hugCorners,\n offset,\n offsetX,\n offsetY,\n flip,\n shift,\n padding,\n },\n };\n}\n"],"mappings":";;;AAQA,MAAa,qBAAqB;CAChC,WAAW;CACX,QAAQ;CACR,OAAO;CACP,YAAY;CACZ,QAAQ;CACR,SAAS;CACT,SAAS;CAGT,MAAM;CACN,OAAO;CACP,SAAS;CACV;AAgBD,MAAM,UAAU,iBAAiB,KAAK;AAEtC,SAAgB,kBACd,UAAoC,EAAE,EACvB;CACf,MAAM,EACJ,YAAY,mBAAmB,WAC/B,SAAS,mBAAmB,QAC5B,QAAQ,mBAAmB,OAC3B,aAAa,mBAAmB,YAChC,SAAS,mBAAmB,QAC5B,UAAU,mBAAmB,SAC7B,UAAU,mBAAmB,SAC7B,UAAU,mBAAmB,SAC7B,aACA,OAAO,cACL;CAMJ,MAAM,OAAO,QAAQ,QAAQ,WAAW;CACxC,MAAM,QAAQ,QAAQ,SAAS,WAAW;CAE1C,MAAM,YAAY,IAAI,QAAQ,MAAM,aAAa,MAAM,OAAO,UAAU;CACxE,MAAM,eAAe,IAAI,QAAQ,SAAS,aAAa,SAAS,MAAM;AAEtE,QAAO;EACL,WAAW;GACT,kBAAkB;GAClB,GAAG,aAAa,MAAM;GACtB,OAAO;GACR;EACD,cAAc;GACZ,kBAAkB;GAClB,GAAG,aAAa,SAAS;GACzB,OAAO;GACR;EACD,SAAS;GACP,MAAM;GACN,SAAS;GACV;EACD,QAAQ;GACN;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACD;EACF"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { AttachmentConfig, HeadlessAttachment } from "./types.js";
|
|
2
|
+
|
|
3
|
+
//#region src/create-attachment.d.ts
|
|
4
|
+
declare function createAttachment(config?: AttachmentConfig): HeadlessAttachment;
|
|
5
|
+
//#endregion
|
|
6
|
+
export { createAttachment };
|
|
7
|
+
//# sourceMappingURL=create-attachment.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-attachment.d.ts","names":[],"sources":["../../src/create-attachment.ts"],"mappings":";;;iBA0DgB,gBAAA,CACd,MAAA,GAAQ,gBAAA,GACP,kBAAA"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { getAttachmentPositionStyles } from "./position-styles.js";
|
|
2
|
+
import { atom } from "nanostores";
|
|
3
|
+
import { autoUpdate, computePosition, flip, offset, shift } from "@floating-ui/dom";
|
|
4
|
+
//#region src/create-attachment.ts
|
|
5
|
+
const DEFAULT_PLACEMENT = "top-end";
|
|
6
|
+
const CORNER_BY_PLACEMENT = {
|
|
7
|
+
top: {
|
|
8
|
+
start: "border-top-left-radius",
|
|
9
|
+
end: "border-top-right-radius"
|
|
10
|
+
},
|
|
11
|
+
bottom: {
|
|
12
|
+
start: "border-bottom-left-radius",
|
|
13
|
+
end: "border-bottom-right-radius"
|
|
14
|
+
},
|
|
15
|
+
right: {
|
|
16
|
+
start: "border-top-right-radius",
|
|
17
|
+
end: "border-bottom-right-radius"
|
|
18
|
+
},
|
|
19
|
+
left: {
|
|
20
|
+
start: "border-top-left-radius",
|
|
21
|
+
end: "border-bottom-left-radius"
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
function readCornerRadius(el, side, align) {
|
|
25
|
+
const raw = getComputedStyle(el).getPropertyValue(CORNER_BY_PLACEMENT[side][align]);
|
|
26
|
+
const px = parseFloat(raw);
|
|
27
|
+
return Number.isFinite(px) && px > 0 ? px : 0;
|
|
28
|
+
}
|
|
29
|
+
function createAttachment(config = {}) {
|
|
30
|
+
const placement = config.placement ?? DEFAULT_PLACEMENT;
|
|
31
|
+
const anchor = config.anchor ?? "corner";
|
|
32
|
+
const shape = config.shape ?? "rect";
|
|
33
|
+
const hugCorners = config.hugCorners ?? false;
|
|
34
|
+
const offsetValue = config.offset ?? 0;
|
|
35
|
+
const offsetX = config.offsetX ?? 0;
|
|
36
|
+
const offsetY = config.offsetY ?? 0;
|
|
37
|
+
const padding = config.padding ?? 0;
|
|
38
|
+
const useFlip = config.flip ?? true;
|
|
39
|
+
const useShift = config.shift ?? true;
|
|
40
|
+
const $positionState = atom({
|
|
41
|
+
x: 0,
|
|
42
|
+
y: 0,
|
|
43
|
+
isPositioned: false
|
|
44
|
+
});
|
|
45
|
+
let targetElement = null;
|
|
46
|
+
let contentElement = null;
|
|
47
|
+
let cleanupAutoUpdate = null;
|
|
48
|
+
const anchorOffset = offset(({ rects, placement: p }) => {
|
|
49
|
+
const [side, align] = p.split("-");
|
|
50
|
+
const vertical = side === "top" || side === "bottom";
|
|
51
|
+
const mainDim = vertical ? rects.floating.height : rects.floating.width;
|
|
52
|
+
const crossDim = vertical ? rects.floating.width : rects.floating.height;
|
|
53
|
+
if (anchor === "outside") return {
|
|
54
|
+
mainAxis: offsetValue,
|
|
55
|
+
crossAxis: 0
|
|
56
|
+
};
|
|
57
|
+
let arcMain = 0;
|
|
58
|
+
let arcCross = 0;
|
|
59
|
+
if (align) {
|
|
60
|
+
let r = 0;
|
|
61
|
+
if (shape === "circle") r = Math.min(rects.reference.width, rects.reference.height) / 2;
|
|
62
|
+
else if (hugCorners && targetElement) r = readCornerRadius(targetElement, side, align);
|
|
63
|
+
const cap = Math.min(rects.reference.width / 2, rects.reference.height / 2);
|
|
64
|
+
r = Math.min(r, cap);
|
|
65
|
+
if (r > 0) {
|
|
66
|
+
const correction = r * (1 - 1 / Math.SQRT2);
|
|
67
|
+
arcMain = -correction;
|
|
68
|
+
arcCross = align === "end" ? -correction : correction;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return {
|
|
72
|
+
mainAxis: -mainDim / 2 + offsetValue + arcMain,
|
|
73
|
+
crossAxis: (align === "end" ? crossDim / 2 : align === "start" ? -crossDim / 2 : 0) + arcCross
|
|
74
|
+
};
|
|
75
|
+
});
|
|
76
|
+
function updatePosition() {
|
|
77
|
+
if (!targetElement || !contentElement) return Promise.resolve();
|
|
78
|
+
const middleware = [anchorOffset];
|
|
79
|
+
if (useFlip) middleware.push(flip({ padding }));
|
|
80
|
+
if (useShift) middleware.push(shift({ padding }));
|
|
81
|
+
return computePosition(targetElement, contentElement, {
|
|
82
|
+
placement,
|
|
83
|
+
strategy: "absolute",
|
|
84
|
+
middleware
|
|
85
|
+
}).then(({ x, y }) => {
|
|
86
|
+
$positionState.set({
|
|
87
|
+
x: x + offsetX,
|
|
88
|
+
y: y + offsetY,
|
|
89
|
+
isPositioned: true
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
function startAutoUpdate() {
|
|
94
|
+
if (!targetElement || !contentElement) return;
|
|
95
|
+
cleanupAutoUpdate = autoUpdate(targetElement, contentElement, updatePosition);
|
|
96
|
+
}
|
|
97
|
+
function stopAutoUpdate() {
|
|
98
|
+
if (cleanupAutoUpdate) {
|
|
99
|
+
cleanupAutoUpdate();
|
|
100
|
+
cleanupAutoUpdate = null;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
$positionState.subscribe((state) => {
|
|
104
|
+
if (!contentElement) return;
|
|
105
|
+
const styles = getAttachmentPositionStyles(state);
|
|
106
|
+
Object.assign(contentElement.style, styles);
|
|
107
|
+
});
|
|
108
|
+
function maybeStart() {
|
|
109
|
+
stopAutoUpdate();
|
|
110
|
+
if (targetElement && contentElement) {
|
|
111
|
+
$positionState.set({
|
|
112
|
+
x: 0,
|
|
113
|
+
y: 0,
|
|
114
|
+
isPositioned: false
|
|
115
|
+
});
|
|
116
|
+
startAutoUpdate();
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
function setTargetElement(el) {
|
|
120
|
+
targetElement = el;
|
|
121
|
+
maybeStart();
|
|
122
|
+
}
|
|
123
|
+
function setContentElement(el) {
|
|
124
|
+
contentElement = el;
|
|
125
|
+
maybeStart();
|
|
126
|
+
}
|
|
127
|
+
function destroy() {
|
|
128
|
+
stopAutoUpdate();
|
|
129
|
+
targetElement = null;
|
|
130
|
+
contentElement = null;
|
|
131
|
+
}
|
|
132
|
+
return {
|
|
133
|
+
$positionState,
|
|
134
|
+
setTargetElement,
|
|
135
|
+
setContentElement,
|
|
136
|
+
destroy
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
//#endregion
|
|
140
|
+
export { createAttachment };
|
|
141
|
+
|
|
142
|
+
//# sourceMappingURL=create-attachment.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-attachment.js","names":["offsetMiddleware","flipMiddleware","shiftMiddleware"],"sources":["../../src/create-attachment.ts"],"sourcesContent":["import { atom } from \"nanostores\";\nimport {\n computePosition,\n autoUpdate,\n flip as flipMiddleware,\n offset as offsetMiddleware,\n shift as shiftMiddleware,\n type ComputePositionReturn,\n type Middleware,\n} from \"@floating-ui/dom\";\nimport { getAttachmentPositionStyles } from \"./position-styles.js\";\nimport type {\n AttachmentConfig,\n HeadlessAttachment,\n PositionState,\n} from \"./types.js\";\n\nconst DEFAULT_PLACEMENT = \"top-end\" as const;\n\ntype Side = \"top\" | \"right\" | \"bottom\" | \"left\";\ntype Align = \"start\" | \"end\";\ntype CornerProperty =\n | \"border-top-left-radius\"\n | \"border-top-right-radius\"\n | \"border-bottom-left-radius\"\n | \"border-bottom-right-radius\";\n\n// Map (side, alignment) → which target corner determines the arc the\n// attachment should hug. e.g. right-end is the bottom-right corner.\nconst CORNER_BY_PLACEMENT: Record<Side, Record<Align, CornerProperty>> = {\n top: {\n start: \"border-top-left-radius\",\n end: \"border-top-right-radius\",\n },\n bottom: {\n start: \"border-bottom-left-radius\",\n end: \"border-bottom-right-radius\",\n },\n right: {\n start: \"border-top-right-radius\",\n end: \"border-bottom-right-radius\",\n },\n left: {\n start: \"border-top-left-radius\",\n end: \"border-bottom-left-radius\",\n },\n};\n\nfunction readCornerRadius(el: HTMLElement, side: Side, align: Align): number {\n const raw = getComputedStyle(el).getPropertyValue(\n CORNER_BY_PLACEMENT[side][align],\n );\n // Computed style returns \"0px\" / \"8px\" / \"8px 4px\" (elliptical). Take the\n // first component — the horizontal radius — which controls the diagonal arc.\n const px = parseFloat(raw);\n return Number.isFinite(px) && px > 0 ? px : 0;\n}\n\nexport function createAttachment(\n config: AttachmentConfig = {},\n): HeadlessAttachment {\n const placement = config.placement ?? DEFAULT_PLACEMENT;\n const anchor = config.anchor ?? \"corner\";\n const shape = config.shape ?? \"rect\";\n const hugCorners = config.hugCorners ?? false;\n const offsetValue = config.offset ?? 0;\n const offsetX = config.offsetX ?? 0;\n const offsetY = config.offsetY ?? 0;\n const padding = config.padding ?? 0;\n const useFlip = config.flip ?? true;\n const useShift = config.shift ?? true;\n\n const $positionState = atom<PositionState>({\n x: 0,\n y: 0,\n isPositioned: false,\n });\n\n let targetElement: HTMLElement | null = null;\n let contentElement: HTMLElement | null = null;\n let cleanupAutoUpdate: (() => void) | null = null;\n\n // For \"corner\" anchoring, pull the attachment back by half its own size so\n // its center sits on the target's edge/corner (badge/stamp/dot convention).\n // For \"outside\", fall back to Floating UI's flush-outside default.\n const anchorOffset: Middleware = offsetMiddleware(\n ({ rects, placement: p }) => {\n const [side, align] = p.split(\"-\") as [\n \"top\" | \"right\" | \"bottom\" | \"left\",\n \"start\" | \"end\" | undefined,\n ];\n const vertical = side === \"top\" || side === \"bottom\";\n const mainDim = vertical ? rects.floating.height : rects.floating.width;\n const crossDim = vertical ? rects.floating.width : rects.floating.height;\n\n if (anchor === \"outside\") {\n return { mainAxis: offsetValue, crossAxis: 0 };\n }\n\n // Diagonal placement on a curved corner: the arc at 45° sits at r/√2\n // from the corner along each axis, whereas the bounding-box corner sits\n // at r. Pull inward by r·(1 − 1/√2) so the attachment hugs the arc.\n // - shape=\"circle\" always applies, with r = min(w,h)/2 (works for masked\n // images / SVGs without a CSS radius).\n // - hugCorners reads the target's actual computed border-radius for the\n // placement corner. Opt-in because it shifts the visual baseline for\n // anything tuned against \"dot center on the bounding-rect corner\".\n let arcMain = 0;\n let arcCross = 0;\n if (align) {\n let r = 0;\n if (shape === \"circle\") {\n r = Math.min(rects.reference.width, rects.reference.height) / 2;\n } else if (hugCorners && targetElement) {\n r = readCornerRadius(targetElement, side, align);\n }\n const cap = Math.min(\n rects.reference.width / 2,\n rects.reference.height / 2,\n );\n r = Math.min(r, cap);\n if (r > 0) {\n const correction = r * (1 - 1 / Math.SQRT2);\n arcMain = -correction;\n arcCross = align === \"end\" ? -correction : correction;\n }\n }\n\n return {\n mainAxis: -mainDim / 2 + offsetValue + arcMain,\n crossAxis:\n (align === \"end\"\n ? crossDim / 2\n : align === \"start\"\n ? -crossDim / 2\n : 0) + arcCross,\n };\n },\n );\n\n function updatePosition(): Promise<void> {\n if (!targetElement || !contentElement) return Promise.resolve();\n\n const middleware: Middleware[] = [anchorOffset];\n if (useFlip) middleware.push(flipMiddleware({ padding }));\n if (useShift) middleware.push(shiftMiddleware({ padding }));\n\n return computePosition(targetElement, contentElement, {\n placement,\n strategy: \"absolute\",\n middleware,\n }).then(({ x, y }: ComputePositionReturn) => {\n $positionState.set({\n x: x + offsetX,\n y: y + offsetY,\n isPositioned: true,\n });\n });\n }\n\n function startAutoUpdate() {\n if (!targetElement || !contentElement) return;\n cleanupAutoUpdate = autoUpdate(\n targetElement,\n contentElement,\n updatePosition,\n );\n }\n\n function stopAutoUpdate() {\n if (cleanupAutoUpdate) {\n cleanupAutoUpdate();\n cleanupAutoUpdate = null;\n }\n }\n\n $positionState.subscribe((state) => {\n if (!contentElement) return;\n const styles = getAttachmentPositionStyles(state);\n Object.assign(contentElement.style, styles);\n });\n\n function maybeStart() {\n stopAutoUpdate();\n if (targetElement && contentElement) {\n $positionState.set({ x: 0, y: 0, isPositioned: false });\n startAutoUpdate();\n }\n }\n\n function setTargetElement(el: HTMLElement | null) {\n targetElement = el;\n maybeStart();\n }\n\n function setContentElement(el: HTMLElement | null) {\n contentElement = el;\n maybeStart();\n }\n\n function destroy() {\n stopAutoUpdate();\n targetElement = null;\n contentElement = null;\n }\n\n return {\n $positionState,\n setTargetElement,\n setContentElement,\n destroy,\n };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { PositionState } from "./types.js";
|
|
2
|
+
|
|
3
|
+
//#region src/position-styles.d.ts
|
|
4
|
+
declare function getAttachmentPositionStyles(state: PositionState): Record<string, string>;
|
|
5
|
+
declare function getAttachmentPositionStyleString(state: PositionState): string;
|
|
6
|
+
//#endregion
|
|
7
|
+
export { getAttachmentPositionStyleString, getAttachmentPositionStyles };
|
|
8
|
+
//# sourceMappingURL=position-styles.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"position-styles.d.ts","names":[],"sources":["../../src/position-styles.ts"],"mappings":";;;iBAEgB,2BAAA,CACd,KAAA,EAAO,aAAA,GACN,MAAA;AAAA,iBAYa,gCAAA,CAAiC,KAAA,EAAO,aAAA"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
//#region src/position-styles.ts
|
|
2
|
+
function getAttachmentPositionStyles(state) {
|
|
3
|
+
return {
|
|
4
|
+
position: "absolute",
|
|
5
|
+
margin: "0",
|
|
6
|
+
left: `${state.x}px`,
|
|
7
|
+
top: `${state.y}px`,
|
|
8
|
+
visibility: state.isPositioned ? "visible" : "hidden",
|
|
9
|
+
opacity: state.isPositioned ? "1" : "0",
|
|
10
|
+
transform: state.isPositioned ? "scale(1)" : "scale(0.85)"
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
function getAttachmentPositionStyleString(state) {
|
|
14
|
+
const styles = getAttachmentPositionStyles(state);
|
|
15
|
+
return Object.entries(styles).map(([k, v]) => `${k}: ${v}`).join("; ");
|
|
16
|
+
}
|
|
17
|
+
//#endregion
|
|
18
|
+
export { getAttachmentPositionStyleString, getAttachmentPositionStyles };
|
|
19
|
+
|
|
20
|
+
//# sourceMappingURL=position-styles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"position-styles.js","names":[],"sources":["../../src/position-styles.ts"],"sourcesContent":["import type { PositionState } from \"./types.js\";\n\nexport function getAttachmentPositionStyles(\n state: PositionState,\n): Record<string, string> {\n return {\n position: \"absolute\",\n margin: \"0\",\n left: `${state.x}px`,\n top: `${state.y}px`,\n visibility: state.isPositioned ? \"visible\" : \"hidden\",\n opacity: state.isPositioned ? \"1\" : \"0\",\n transform: state.isPositioned ? \"scale(1)\" : \"scale(0.85)\",\n };\n}\n\nexport function getAttachmentPositionStyleString(state: PositionState): string {\n const styles = getAttachmentPositionStyles(state);\n return Object.entries(styles)\n .map(([k, v]) => `${k}: ${v}`)\n .join(\"; \");\n}\n"],"mappings":";AAEA,SAAgB,4BACd,OACwB;AACxB,QAAO;EACL,UAAU;EACV,QAAQ;EACR,MAAM,GAAG,MAAM,EAAE;EACjB,KAAK,GAAG,MAAM,EAAE;EAChB,YAAY,MAAM,eAAe,YAAY;EAC7C,SAAS,MAAM,eAAe,MAAM;EACpC,WAAW,MAAM,eAAe,aAAa;EAC9C;;AAGH,SAAgB,iCAAiC,OAA8B;CAC7E,MAAM,SAAS,4BAA4B,MAAM;AACjD,QAAO,OAAO,QAAQ,OAAO,CAC1B,KAAK,CAAC,GAAG,OAAO,GAAG,EAAE,IAAI,IAAI,CAC7B,KAAK,KAAK"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import * as _$nanostores from "nanostores";
|
|
2
|
+
import { Placement } from "@floating-ui/dom";
|
|
3
|
+
import { SystemStyleObject } from "@pindoba/styled-system/types";
|
|
4
|
+
|
|
5
|
+
//#region src/types.d.ts
|
|
6
|
+
type ElementAttributes = Partial<Record<string, unknown>>;
|
|
7
|
+
interface AttachmentSlotPassThrough<T = ElementAttributes> {
|
|
8
|
+
style?: SystemStyleObject;
|
|
9
|
+
props?: T;
|
|
10
|
+
}
|
|
11
|
+
interface AttachmentPassThrough<RootElementAttributes = ElementAttributes, ContentElementAttributes = ElementAttributes> {
|
|
12
|
+
root?: AttachmentSlotPassThrough<RootElementAttributes>;
|
|
13
|
+
content?: AttachmentSlotPassThrough<ContentElementAttributes>;
|
|
14
|
+
}
|
|
15
|
+
interface PositionState {
|
|
16
|
+
x: number;
|
|
17
|
+
y: number;
|
|
18
|
+
isPositioned: boolean;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* How the attachment is anchored to the target.
|
|
22
|
+
* - "corner" (default): the attachment's center sits on the target's corner/edge —
|
|
23
|
+
* the natural fit for badges, dots, stamps that should overlap half in / half out.
|
|
24
|
+
* - "outside": the attachment sits fully outside the target, flush against its edge
|
|
25
|
+
* (standard Floating UI popover/tooltip behavior).
|
|
26
|
+
*/
|
|
27
|
+
type AttachmentAnchor = "corner" | "outside";
|
|
28
|
+
/**
|
|
29
|
+
* Silhouette of the target element. "rect" uses the bounding-box corner;
|
|
30
|
+
* "circle" pulls the attachment inward along the arc so diagonal placements
|
|
31
|
+
* hug a circular target instead of floating off its bounding corner.
|
|
32
|
+
*/
|
|
33
|
+
type AttachmentShape = "rect" | "circle";
|
|
34
|
+
interface AttachmentConfig {
|
|
35
|
+
/** Floating UI placement. Default: "top-end". */
|
|
36
|
+
placement?: Placement;
|
|
37
|
+
/** Where the attachment sits relative to the target bounds. Default: "corner". */
|
|
38
|
+
anchor?: AttachmentAnchor;
|
|
39
|
+
/** Silhouette of the target. Default: "rect". */
|
|
40
|
+
shape?: AttachmentShape;
|
|
41
|
+
/**
|
|
42
|
+
* Pull the attachment inward along the diagonal so it hugs the target's
|
|
43
|
+
* rounded corner instead of sitting on the bounding-box corner. Reads the
|
|
44
|
+
* target's computed `border-*-radius` for the placement corner. Default:
|
|
45
|
+
* false. Ignored when `shape="circle"` (which always hugs the arc).
|
|
46
|
+
*/
|
|
47
|
+
hugCorners?: boolean;
|
|
48
|
+
/** Extra px nudge along the placement axes, stacked on top of the anchor. Default: 0. */
|
|
49
|
+
offset?: number;
|
|
50
|
+
/** Extra px nudge on the horizontal axis, applied after all positioning. Default: 0. */
|
|
51
|
+
offsetX?: number;
|
|
52
|
+
/** Extra px nudge on the vertical axis, applied after all positioning. Default: 0. */
|
|
53
|
+
offsetY?: number;
|
|
54
|
+
/**
|
|
55
|
+
* Flip to the opposite side when overflowing the viewport.
|
|
56
|
+
* Default: `false` for `anchor="corner"` (a corner indicator should stay on
|
|
57
|
+
* its requested corner), `true` for `anchor="outside"` (popover-like).
|
|
58
|
+
*/
|
|
59
|
+
flip?: boolean;
|
|
60
|
+
/**
|
|
61
|
+
* Shift along the alignment axis to stay within the viewport.
|
|
62
|
+
* Default: `false` for `anchor="corner"`, `true` for `anchor="outside"`.
|
|
63
|
+
*/
|
|
64
|
+
shift?: boolean;
|
|
65
|
+
/** Padding (px) used by flip/shift middleware for viewport boundary. Default: 0. */
|
|
66
|
+
padding?: number;
|
|
67
|
+
}
|
|
68
|
+
interface HeadlessAttachment {
|
|
69
|
+
$positionState: _$nanostores.WritableAtom<PositionState>;
|
|
70
|
+
setTargetElement: (el: HTMLElement | null) => void;
|
|
71
|
+
setContentElement: (el: HTMLElement | null) => void;
|
|
72
|
+
destroy: () => void;
|
|
73
|
+
}
|
|
74
|
+
interface AttachmentBaseProps<RootElementAttributes = ElementAttributes, ContentElementAttributes = ElementAttributes> {
|
|
75
|
+
placement?: Placement;
|
|
76
|
+
anchor?: AttachmentAnchor;
|
|
77
|
+
shape?: AttachmentShape;
|
|
78
|
+
hugCorners?: boolean;
|
|
79
|
+
offset?: number;
|
|
80
|
+
offsetX?: number;
|
|
81
|
+
offsetY?: number;
|
|
82
|
+
flip?: boolean;
|
|
83
|
+
shift?: boolean;
|
|
84
|
+
padding?: number;
|
|
85
|
+
passThrough?: AttachmentPassThrough<RootElementAttributes, ContentElementAttributes>;
|
|
86
|
+
}
|
|
87
|
+
type ConnectAttachmentOptions = AttachmentBaseProps<object, object> & {
|
|
88
|
+
class?: unknown;
|
|
89
|
+
};
|
|
90
|
+
interface AttachmentRootProps {
|
|
91
|
+
class: string;
|
|
92
|
+
"data-component": "attachment";
|
|
93
|
+
[key: string]: unknown;
|
|
94
|
+
}
|
|
95
|
+
interface AttachmentContentProps {
|
|
96
|
+
class: string;
|
|
97
|
+
"data-component": "attachment-content";
|
|
98
|
+
[key: string]: unknown;
|
|
99
|
+
}
|
|
100
|
+
interface AttachmentClasses {
|
|
101
|
+
root: string;
|
|
102
|
+
content: string;
|
|
103
|
+
}
|
|
104
|
+
interface AttachmentApi {
|
|
105
|
+
rootProps: AttachmentRootProps;
|
|
106
|
+
contentProps: AttachmentContentProps;
|
|
107
|
+
classes: AttachmentClasses;
|
|
108
|
+
config: Required<Pick<AttachmentConfig, "placement" | "anchor" | "shape" | "hugCorners" | "offset" | "offsetX" | "offsetY" | "flip" | "shift" | "padding">>;
|
|
109
|
+
}
|
|
110
|
+
//#endregion
|
|
111
|
+
export { AttachmentAnchor, AttachmentApi, AttachmentBaseProps, AttachmentClasses, AttachmentConfig, AttachmentContentProps, AttachmentPassThrough, AttachmentRootProps, AttachmentShape, AttachmentSlotPassThrough, ConnectAttachmentOptions, ElementAttributes, HeadlessAttachment, type Placement, PositionState };
|
|
112
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","names":[],"sources":["../../src/types.ts"],"mappings":";;;;;KAKY,iBAAA,GAAoB,OAAA,CAAQ,MAAA;AAAA,UAEvB,yBAAA,KAA8B,iBAAA;EAC7C,KAAA,GAAQ,iBAAA;EACR,KAAA,GAAQ,CAAA;AAAA;AAAA,UAGO,qBAAA,yBACS,iBAAA,6BACG,iBAAA;EAE3B,IAAA,GAAO,yBAAA,CAA0B,qBAAA;EACjC,OAAA,GAAU,yBAAA,CAA0B,wBAAA;AAAA;AAAA,UAGrB,aAAA;EACf,CAAA;EACA,CAAA;EACA,YAAA;AAAA;;;;;;;;KAUU,gBAAA;;AArBZ;;;;KA4BY,eAAA;AAAA,UAEK,gBAAA;EA1BR;EA4BP,SAAA,GAAY,SAAA;EA3BF;EA6BV,MAAA,GAAS,gBAAA;EA7B0B;EA+BnC,KAAA,GAAQ,eAAA;EAnCgB;;;;;;EA0CxB,UAAA;EAtCU;EAwCV,MAAA;EAxC4D;EA0C5D,OAAA;EAvCe;EAyCf,OAAA;;;;;;EAMA,IAAA;EA5CY;AAUd;;;EAuCE,KAAA;EAvC0B;EAyC1B,OAAA;AAAA;AAAA,UAGe,kBAAA;EACf,cAAA,EAA+D,YAAA,CAA1B,YAAA,CAAa,aAAA;EAClD,gBAAA,GAAmB,EAAA,EAAI,WAAA;EACvB,iBAAA,GAAoB,EAAA,EAAI,WAAA;EACxB,OAAA;AAAA;AAAA,UAGe,mBAAA,yBACS,iBAAA,6BACG,iBAAA;EAE3B,SAAA,GAAY,SAAA;EACZ,MAAA,GAAS,gBAAA;EACT,KAAA,GAAQ,eAAA;EACR,UAAA;EACA,MAAA;EACA,OAAA;EACA,OAAA;EACA,IAAA;EACA,KAAA;EACA,OAAA;EACA,WAAA,GAAc,qBAAA,CACZ,qBAAA,EACA,wBAAA;AAAA;AAAA,KAIQ,wBAAA,GAA2B,mBAAA;EACrC,KAAA;AAAA;AAAA,UAGe,mBAAA;EACf,KAAA;EACA,gBAAA;EAAA,CACC,GAAA;AAAA;AAAA,UAGc,sBAAA;EACf,KAAA;EACA,gBAAA;EAAA,CACC,GAAA;AAAA;AAAA,UAGc,iBAAA;EACf,IAAA;EACA,OAAA;AAAA;AAAA,UAGe,aAAA;EACf,SAAA,EAAW,mBAAA;EACX,YAAA,EAAc,sBAAA;EACd,OAAA,EAAS,iBAAA;EACT,MAAA,EAAQ,QAAA,CACN,IAAA,CACE,gBAAA;AAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@pindoba/core-attachment",
|
|
3
|
+
"version": "0.0.0-alpha-20260426220647",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"sideEffects": false,
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./*": {
|
|
15
|
+
"types": "./dist/src/*.d.ts",
|
|
16
|
+
"import": "./dist/src/*.js"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"dist"
|
|
21
|
+
],
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"@floating-ui/dom": "^1.7.6",
|
|
24
|
+
"nanostores": "^1.3.0",
|
|
25
|
+
"@pindoba/styled-system": "0.0.0-alpha-20260426220647",
|
|
26
|
+
"@pindoba/styles-attachment": "0.0.0-alpha-20260426220647"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"tsdown": "^0.21.10",
|
|
30
|
+
"typescript": "^6.0.3"
|
|
31
|
+
},
|
|
32
|
+
"scripts": {
|
|
33
|
+
"build": "tsdown",
|
|
34
|
+
"dev": "tsdown --watch",
|
|
35
|
+
"clean": "rm -rf dist && rm -rf node_modules && rm -rf .turbo"
|
|
36
|
+
}
|
|
37
|
+
}
|