purse-styles 0.0.1
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.md +21 -0
- package/README.md +90 -0
- package/dist/clsx.d.ts +1 -0
- package/dist/cssVar.d.ts +2 -0
- package/dist/destructors.d.ts +2 -0
- package/dist/hashObject.d.ts +1 -0
- package/dist/hyphenateStyleName.d.ts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +411 -0
- package/dist/index.js.map +6 -0
- package/dist/purse.d.ts +42 -0
- package/dist/useRequiredContext.d.ts +2 -0
- package/package.json +44 -0
- package/src/clsx.ts +3 -0
- package/src/cssVar.ts +5 -0
- package/src/destructors.ts +7 -0
- package/src/hashObject.ts +25 -0
- package/src/hyphenateStyleName.ts +16 -0
- package/src/index.ts +11 -0
- package/src/purse.test.ts +97 -0
- package/src/purse.tsx +576 -0
- package/src/useRequiredContext.tsx +11 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
function toAlphabeticChar(code: number) {
|
|
2
|
+
return String.fromCharCode(code + (code > 25 ? 39 : 97))
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
function toAlphabeticName(code: number) {
|
|
6
|
+
let name = ""
|
|
7
|
+
let x
|
|
8
|
+
|
|
9
|
+
for (x = Math.abs(code); x > 52; x = (x / 52) | 0)
|
|
10
|
+
name = toAlphabeticChar(x % 52) + name
|
|
11
|
+
|
|
12
|
+
return toAlphabeticChar(x % 52) + name
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function toPhash(h: number, x: string) {
|
|
16
|
+
let i = x.length
|
|
17
|
+
while (i) {
|
|
18
|
+
i--
|
|
19
|
+
h = (h * 33) ^ x.charCodeAt(i)
|
|
20
|
+
}
|
|
21
|
+
return h
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export const hashObject = (value: Object) =>
|
|
25
|
+
toAlphabeticName(toPhash(5381, JSON.stringify(value)) >>> 0)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
const uppercasePattern = /[A-Z]/g
|
|
2
|
+
const msPattern = /^ms-/
|
|
3
|
+
const cache: { [key: string]: string } = {}
|
|
4
|
+
|
|
5
|
+
function toHyphenLower(match: string) {
|
|
6
|
+
return "-" + match.toLowerCase()
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function hyphenateStyleName(name: string) {
|
|
10
|
+
if (cache.hasOwnProperty(name)) {
|
|
11
|
+
return cache[name]
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
var hName = name.replace(uppercasePattern, toHyphenLower)
|
|
15
|
+
return (cache[name] = msPattern.test(hName) ? "-" + hName : hName)
|
|
16
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import assert from "assert"
|
|
2
|
+
import { expect } from "extendable-expect"
|
|
3
|
+
import { describe, it } from "vitest"
|
|
4
|
+
import { InMemoryStyleApi, createInMemoryStyleApi, style } from "./purse"
|
|
5
|
+
|
|
6
|
+
describe("Purse", () => {
|
|
7
|
+
const expectStyles = expect.extend({
|
|
8
|
+
toContainRule(api: InMemoryStyleApi, expectedRuleToContain: string) {
|
|
9
|
+
expect(api.styleRulesRef.current).toContain(expectedRuleToContain)
|
|
10
|
+
},
|
|
11
|
+
toOnlyContainRules(
|
|
12
|
+
api: InMemoryStyleApi,
|
|
13
|
+
expectedRulesToContain: string[],
|
|
14
|
+
) {
|
|
15
|
+
for (const expectedRule of expectedRulesToContain) {
|
|
16
|
+
expect(api.styleRulesRef.current).toContain(expectedRule)
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
toHaveCount(api: InMemoryStyleApi, expectedCount: number) {
|
|
20
|
+
expect(api.styleRulesRef.current).toHaveLength(expectedCount)
|
|
21
|
+
},
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
it("Compiles correctly", () => {
|
|
25
|
+
const test = style({
|
|
26
|
+
accentColor: "blue",
|
|
27
|
+
borderColor: "blue",
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
assert(test.owned !== undefined)
|
|
31
|
+
expect(test.owned.styleRules).toContain(
|
|
32
|
+
`.${test.className}{accent-color:blue;border-color:blue;}`,
|
|
33
|
+
)
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
it("Compiles simple pseudo selectors", () => {
|
|
37
|
+
const api = createInMemoryStyleApi()
|
|
38
|
+
|
|
39
|
+
const test = style({
|
|
40
|
+
"@media (hover: hover)": {
|
|
41
|
+
backgroundColor: "blue",
|
|
42
|
+
},
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
api.addStyleElement(test)
|
|
46
|
+
expectStyles(api).toOnlyContainRules([
|
|
47
|
+
`@media (hover: hover){.${test.className}{background-color:blue;}}`,
|
|
48
|
+
])
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
it("Compiles simple at selectors", () => {
|
|
52
|
+
const api = createInMemoryStyleApi()
|
|
53
|
+
|
|
54
|
+
const test = style({
|
|
55
|
+
"&:disabled": {
|
|
56
|
+
backgroundColor: "blue",
|
|
57
|
+
},
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
api.addStyleElement(test)
|
|
61
|
+
expectStyles(api).toOnlyContainRules([
|
|
62
|
+
`.${test.className}:disabled{background-color:blue;}`,
|
|
63
|
+
])
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
it("Compiles multiple pseudo selectors", () => {
|
|
67
|
+
const api = createInMemoryStyleApi()
|
|
68
|
+
|
|
69
|
+
const test = style({
|
|
70
|
+
"&:disabled": {
|
|
71
|
+
backgroundColor: "blue",
|
|
72
|
+
},
|
|
73
|
+
"&:disabled:hover": {
|
|
74
|
+
backgroundColor: "red",
|
|
75
|
+
},
|
|
76
|
+
"&:hover": {
|
|
77
|
+
backgroundColor: "green",
|
|
78
|
+
},
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
api.addStyleElement(test)
|
|
82
|
+
|
|
83
|
+
expectStyles(api).toOnlyContainRules([
|
|
84
|
+
`.${test.className}:disabled{background-color:blue;}`,
|
|
85
|
+
`.${test.className}:disabled:hover{background-color:red;}`,
|
|
86
|
+
`.${test.className}:hover{background-color:green;}`,
|
|
87
|
+
])
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
it.skip("Inserts into given style element correctly", () => {})
|
|
91
|
+
it.skip("Works if you pass style rule or object to useStyles", () => {})
|
|
92
|
+
it.skip("Works if you pass multiple style rule or object to useStyles", () => {})
|
|
93
|
+
it.skip("Inserts browser prefixes", () => {})
|
|
94
|
+
|
|
95
|
+
it.skip("Inserting two styles with shared style object then removing one", () => {})
|
|
96
|
+
it.skip("Inserting two styles with shared style object then removing both", () => {})
|
|
97
|
+
})
|