-
-
Notifications
You must be signed in to change notification settings - Fork 93
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
next:
Portal
utility component (#716)
- Loading branch information
Showing
13 changed files
with
191 additions
and
31 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"bits-ui": patch | ||
--- | ||
|
||
feat: export and document `Portal` utility component |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
const NUMBER_CHAR_RE = /\d/; | ||
const STR_SPLITTERS = ["-", "_", "/", "."]; | ||
|
||
function isUppercase(char = ""): boolean | undefined { | ||
if (NUMBER_CHAR_RE.test(char)) return undefined; | ||
return char !== char.toLowerCase(); | ||
} | ||
|
||
function splitByCase(str: string) { | ||
const parts: string[] = []; | ||
|
||
let buff = ""; | ||
|
||
let previousUpper: boolean | undefined; | ||
let previousSplitter: boolean | undefined; | ||
|
||
for (const char of str) { | ||
// Splitter | ||
const isSplitter = STR_SPLITTERS.includes(char); | ||
if (isSplitter === true) { | ||
parts.push(buff); | ||
buff = ""; | ||
previousUpper = undefined; | ||
continue; | ||
} | ||
|
||
const isUpper = isUppercase(char); | ||
if (previousSplitter === false) { | ||
// Case rising edge | ||
if (previousUpper === false && isUpper === true) { | ||
parts.push(buff); | ||
buff = char; | ||
previousUpper = isUpper; | ||
continue; | ||
} | ||
// Case falling edge | ||
if (previousUpper === true && isUpper === false && buff.length > 1) { | ||
const lastChar = buff.at(-1); | ||
parts.push(buff.slice(0, Math.max(0, buff.length - 1))); | ||
buff = lastChar + char; | ||
previousUpper = isUpper; | ||
continue; | ||
} | ||
} | ||
|
||
// Normal char | ||
buff += char; | ||
previousUpper = isUpper; | ||
previousSplitter = isSplitter; | ||
} | ||
|
||
parts.push(buff); | ||
|
||
return parts; | ||
} | ||
|
||
export function pascalCase(str?: string) { | ||
if (!str) return ""; | ||
return splitByCase(str) | ||
.map((p) => upperFirst(p)) | ||
.join(""); | ||
} | ||
|
||
export function camelCase(str?: string) { | ||
return lowerFirst(pascalCase(str || "")); | ||
} | ||
|
||
export function kebabCase(str?: string) { | ||
return str | ||
? splitByCase(str) | ||
.map((p) => p.toLowerCase()) | ||
.join("-") | ||
: ""; | ||
} | ||
|
||
function upperFirst(str: string) { | ||
return str ? str[0]!.toUpperCase() + str.slice(1) : ""; | ||
} | ||
|
||
function lowerFirst(str: string) { | ||
return str ? str[0]!.toLowerCase() + str.slice(1) : ""; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
function createParser(matcher: string | RegExp, replacer: (match: string) => string) { | ||
const regex = RegExp(matcher, "g"); | ||
return (str: string): string => { | ||
// throw an error if not a string | ||
if (typeof str !== "string") { | ||
throw new TypeError(`expected an argument of type string, but got ${typeof str}`); | ||
} | ||
|
||
// if no match between string and matcher | ||
if (!str.match(regex)) return str; | ||
|
||
// executes the replacer function for each match | ||
return str.replace(regex, replacer); | ||
}; | ||
} | ||
|
||
const camelToKebab = createParser(/[A-Z]/, (match) => `-${match.toLowerCase()}`); | ||
|
||
export function styleToCSS(styleObj: object) { | ||
if (!styleObj || typeof styleObj !== "object" || Array.isArray(styleObj)) { | ||
throw new TypeError(`expected an argument of type object, but got ${typeof styleObj}`); | ||
} | ||
return Object.keys(styleObj) | ||
.map( | ||
(property) => | ||
`${camelToKebab(property)}: ${styleObj[property as keyof typeof styleObj]};` | ||
) | ||
.join("\n"); | ||
} |
10 changes: 0 additions & 10 deletions
10
packages/bits-ui/src/lib/shared/style-object-to-css-string.d.ts
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
--- | ||
title: Portal | ||
description: A component that renders its children in a portal, preventing layout issues in complex UI structures. | ||
--- | ||
|
||
## Overview | ||
|
||
The Portal component is a utility component that renders its children in a portal, preventing layout issues in complex UI structures. This component is used for the various Bits UI component that have a `Portal` sub-component. | ||
|
||
## Usage | ||
|
||
### Default behavior | ||
|
||
By default, the `Portal` component will render its children in the `body` element. | ||
|
||
```svelte | ||
<script lang="ts"> | ||
import { Portal } from "bits-ui"; | ||
</script> | ||
<Portal> | ||
<div>This content will be portalled to the body</div> | ||
</Portal> | ||
``` | ||
|
||
### Custom target | ||
|
||
You can use the `to` prop to specify a custom target element or selector to render the content to. | ||
|
||
```svelte | ||
<script lang="ts"> | ||
import { Portal } from "bits-ui"; | ||
</script> | ||
<div id="custom-target"></div> | ||
<div> | ||
<Portal to="#custom-target"> | ||
<div>This content will be portalled to the #custom-target element</div> | ||
</Portal> | ||
</div> | ||
``` | ||
|
||
### Disable | ||
|
||
You can use the `disabled` prop to disable the portal behavior. | ||
|
||
```svelte | ||
<script lang="ts"> | ||
import { Portal } from "bits-ui"; | ||
</script> | ||
<Portal disabled> | ||
<div>This content will not be portalled</div> | ||
</Portal> | ||
``` |