From 5d8d972d25191eb2c21d7fdbac027672da95f51d Mon Sep 17 00:00:00 2001 From: SpikeySanju Date: Sun, 10 Nov 2024 18:14:42 +0530 Subject: [PATCH] Initial commit --- .github/workflows/ci.yml | 37 ++++ .gitignore | 22 ++ .npmrc | 1 + .prettierignore | 4 + .prettierrc | 15 ++ README.md | 257 ++++++++++++++++++++++ bun.lockb | Bin 0 -> 135326 bytes eslint.config.js | 33 +++ package.json | 75 +++++++ postcss.config.js | 6 + src/app.css | 3 + src/app.d.ts | 13 ++ src/app.html | 12 + src/demo.spec.ts | 7 + src/lib/actions/draggable.ts | 49 +++++ src/lib/actions/droppable.ts | 71 ++++++ src/lib/actions/index.ts | 2 + src/lib/index.ts | 11 + src/lib/stores/dnd.svelte.ts | 9 + src/lib/styles/dnd.css | 37 ++++ src/lib/types/index.ts | 22 ++ src/routes/+layout.svelte | 60 +++++ src/routes/+page.svelte | 153 +++++++++++++ src/routes/grid-sort/+page.svelte | 58 +++++ src/routes/horizontal-scroll/+page.svelte | 60 +++++ src/routes/nested/+page.svelte | 188 ++++++++++++++++ src/routes/simple-list/+page.svelte | 105 +++++++++ static/favicon.png | Bin 0 -> 1571 bytes svelte.config.js | 18 ++ tailwind.config.ts | 11 + tsconfig.json | 15 ++ vite.config.ts | 10 + 32 files changed, 1364 insertions(+) create mode 100644 .github/workflows/ci.yml create mode 100644 .gitignore create mode 100644 .npmrc create mode 100644 .prettierignore create mode 100644 .prettierrc create mode 100644 README.md create mode 100755 bun.lockb create mode 100644 eslint.config.js create mode 100644 package.json create mode 100644 postcss.config.js create mode 100644 src/app.css create mode 100644 src/app.d.ts create mode 100644 src/app.html create mode 100644 src/demo.spec.ts create mode 100644 src/lib/actions/draggable.ts create mode 100644 src/lib/actions/droppable.ts create mode 100644 src/lib/actions/index.ts create mode 100644 src/lib/index.ts create mode 100644 src/lib/stores/dnd.svelte.ts create mode 100644 src/lib/styles/dnd.css create mode 100644 src/lib/types/index.ts create mode 100644 src/routes/+layout.svelte create mode 100644 src/routes/+page.svelte create mode 100644 src/routes/grid-sort/+page.svelte create mode 100644 src/routes/horizontal-scroll/+page.svelte create mode 100644 src/routes/nested/+page.svelte create mode 100644 src/routes/simple-list/+page.svelte create mode 100644 static/favicon.png create mode 100644 svelte.config.js create mode 100644 tailwind.config.ts create mode 100644 tsconfig.json create mode 100644 vite.config.ts diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..7456665 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,37 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + - run: npm ci + - run: npm run check + - run: npm run lint + - run: npm test + + publish: + needs: test + runs-on: ubuntu-latest + if: github.ref == 'refs/heads/main' + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: '20' + registry-url: 'https://registry.npmjs.org' + - run: npm ci + - run: npm run build + - run: npm publish + env: + NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..715b548 --- /dev/null +++ b/.gitignore @@ -0,0 +1,22 @@ +node_modules + +# Output +.output +.vercel +/.svelte-kit +/build +/dist + +# OS +.DS_Store +Thumbs.db + +# Env +.env +.env.* +!.env.example +!.env.test + +# Vite +vite.config.js.timestamp-* +vite.config.ts.timestamp-* diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..b6f27f1 --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +engine-strict=true diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..ab78a95 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,4 @@ +# Package Managers +package-lock.json +pnpm-lock.yaml +yarn.lock diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..7ebb855 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,15 @@ +{ + "useTabs": true, + "singleQuote": true, + "trailingComma": "none", + "printWidth": 100, + "plugins": ["prettier-plugin-svelte", "prettier-plugin-tailwindcss"], + "overrides": [ + { + "files": "*.svelte", + "options": { + "parser": "svelte" + } + } + ] +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..f13e9ec --- /dev/null +++ b/README.md @@ -0,0 +1,257 @@ +# SvelteDnD + +A lightweight drag and drop library for Svelte 5 applications. Built with TypeScript and Svelte's new runes system. + +## Installation + +```bash +npm install sveltednd +``` + +## Quick Start + +```typescript +import { draggable, droppable } from 'sveltednd'; +import 'sveltednd/styles.css'; + +// Create a list of items +let items = $state(['Item 1', 'Item 2', 'Item 3']); + +// Handle drops between containers +function handleDrop(state) { + const { draggedItem, sourceContainer, targetContainer } = state; + if (!targetContainer || sourceContainer === targetContainer) return; + + items = items.filter((item) => item !== draggedItem); + items = [...items, draggedItem]; +} +``` + +```svelte + +
+ {#each items as item} + +
+ {item} +
+ {/each} +
+``` + +## Core Concepts + +### 1. Draggable Items + +- Add `use:draggable` to make elements draggable +- Specify container ID and data to transfer +- Optional callbacks for drag start/end + +### 2. Droppable Containers + +- Add `use:droppable` to create drop zones +- Handle drops via callbacks +- Visual feedback during drag operations + +### 3. State Management + +- Built-in state tracking via Svelte 5 runes +- Access current drag state via `dndState` store +- Automatic cleanup and memory management + +## API Reference + +### Draggable Action + +```typescript +interface DraggableOptions { + container: string; // Container identifier + dragData: any; // Data to transfer + disabled?: boolean; // Disable dragging + callbacks?: { + onDragStart?: (state: DragDropState) => void; + onDragEnd?: (state: DragDropState) => void; + } +} + +// Usage +
console.log('Started dragging', state) + } +}}> +``` + +### Droppable Action + +```typescript +interface DroppableOptions { + container: string; // Container identifier + disabled?: boolean; // Disable dropping + callbacks?: { + onDragEnter?: (state: DragDropState) => void; + onDragLeave?: (state: DragDropState) => void; + onDragOver?: (state: DragDropState) => void; + onDrop?: (state: DragDropState) => Promise | void; + } +} + +// Usage +
handleDrop(state) + } +}}> +``` + +### DragDropState Interface + +```typescript +interface DragDropState { + isDragging: boolean; // Current drag status + draggedItem: any; // Item being dragged + sourceContainer: string; // Origin container ID + targetContainer: string | null; // Current target container ID +} +``` + +## Examples + +### Basic List + +```svelte + + +
+ {#each items as item} +
+ {item} +
+ {/each} +
+``` + +### Multiple Containers + +```svelte + + +
+
+ {#each container1 as item} +
+ {item} +
+ {/each} +
+ +
+ {#each container2 as item} +
+ {item} +
+ {/each} +
+
+``` + +### Conditional Dropping + +```svelte + + +
+``` + +## Styling + +The library provides CSS classes for styling drag and drop states: + +```css +/* Base styles */ +.svelte-dnd-draggable { + cursor: grab; +} + +/* Active dragging */ +.svelte-dnd-dragging { + opacity: 0.5; + cursor: grabbing; +} + +/* Valid drop target */ +.svelte-dnd-drop-target { + outline: 2px dashed #4caf50; +} + +/* Invalid drop target */ +.svelte-dnd-invalid-target { + outline: 2px dashed #f44336; +} +``` + +## TypeScript Support + +The library is written in TypeScript and provides full type definitions. Use interfaces to type your dragged items: + +```typescript +interface Task { + id: string; + title: string; +} + +function handleDrop(state: DragDropState) { + const draggedTask = state.draggedItem as Task; + // TypeScript now knows the shape of draggedTask +} +``` + +## Performance Tips + +1. Use unique IDs as keys in loops +2. Keep drag data minimal +3. Avoid expensive operations in drag callbacks +4. Use `$derived` for computed values + +## License + +MIT diff --git a/bun.lockb b/bun.lockb new file mode 100755 index 0000000000000000000000000000000000000000..7f4e3ea2c801aab2355f65d892effd00fa371b4b GIT binary patch literal 135326 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
    uXjDBS@}9uBj-}L;YY39fx>efH46&X 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 literal 0 HcmV?d00001 diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000..a526565 --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,33 @@ +import prettier from 'eslint-config-prettier'; +import js from '@eslint/js'; +import svelte from 'eslint-plugin-svelte'; +import globals from 'globals'; +import ts from 'typescript-eslint'; + +export default ts.config( + js.configs.recommended, + ...ts.configs.recommended, + ...svelte.configs['flat/recommended'], + prettier, + ...svelte.configs['flat/prettier'], + { + languageOptions: { + globals: { + ...globals.browser, + ...globals.node + } + } + }, + { + files: ['**/*.svelte'], + + languageOptions: { + parserOptions: { + parser: ts.parser + } + } + }, + { + ignores: ['build/', '.svelte-kit/', 'dist/'] + } +); diff --git a/package.json b/package.json new file mode 100644 index 0000000..fd19805 --- /dev/null +++ b/package.json @@ -0,0 +1,75 @@ +{ + "name": "sveltednd", + "version": "0.0.1", + "description": "A lightweight, flexible drag and drop library for Svelte 5 applications.", + "author": "sanju ", + "contributors": [ + "sanju " + ], + "license": "MIT", + "keywords": [ + "svelte", + "drag", + "drop", + "dnd", + "drag-and-drop", + "typescript", + "svelte5" + ], + "scripts": { + "dev": "vite dev", + "build": "vite build && npm run package", + "preview": "vite preview", + "package": "svelte-kit sync && svelte-package && publint", + "prepublishOnly": "npm run package", + "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", + "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", + "format": "prettier --write .", + "lint": "prettier --check . && eslint .", + "test:unit": "vitest", + "test": "npm run test:unit -- --run" + }, + "files": [ + "dist", + "!dist/**/*.test.*", + "!dist/**/*.spec.*" + ], + "sideEffects": [ + "**/*.css" + ], + "svelte": "./dist/index.js", + "types": "./dist/index.d.ts", + "type": "module", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "svelte": "./dist/index.js" + } + }, + "peerDependencies": { + "svelte": "^5.0.0" + }, + "devDependencies": { + "@sveltejs/adapter-auto": "^3.0.0", + "@sveltejs/kit": "^2.0.0", + "@sveltejs/package": "^2.0.0", + "@sveltejs/vite-plugin-svelte": "^4.0.0", + "@types/eslint": "^9.6.0", + "autoprefixer": "^10.4.20", + "eslint": "^9.7.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-svelte": "^2.36.0", + "globals": "^15.0.0", + "prettier": "^3.3.2", + "prettier-plugin-svelte": "^3.2.6", + "prettier-plugin-tailwindcss": "^0.6.5", + "publint": "^0.2.0", + "svelte": "^5.0.0", + "svelte-check": "^4.0.0", + "tailwindcss": "^3.4.9", + "typescript": "^5.0.0", + "typescript-eslint": "^8.0.0", + "vite": "^5.0.11", + "vitest": "^2.0.4" + } +} diff --git a/postcss.config.js b/postcss.config.js new file mode 100644 index 0000000..0f77216 --- /dev/null +++ b/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {} + } +}; diff --git a/src/app.css b/src/app.css new file mode 100644 index 0000000..a31e444 --- /dev/null +++ b/src/app.css @@ -0,0 +1,3 @@ +@import 'tailwindcss/base'; +@import 'tailwindcss/components'; +@import 'tailwindcss/utilities'; diff --git a/src/app.d.ts b/src/app.d.ts new file mode 100644 index 0000000..da08e6d --- /dev/null +++ b/src/app.d.ts @@ -0,0 +1,13 @@ +// See https://svelte.dev/docs/kit/types#app.d.ts +// for information about these interfaces +declare global { + namespace App { + // interface Error {} + // interface Locals {} + // interface PageData {} + // interface PageState {} + // interface Platform {} + } +} + +export {}; diff --git a/src/app.html b/src/app.html new file mode 100644 index 0000000..f22aeaa --- /dev/null +++ b/src/app.html @@ -0,0 +1,12 @@ + + + + + + + %sveltekit.head% + + +
    %sveltekit.body%
    + + diff --git a/src/demo.spec.ts b/src/demo.spec.ts new file mode 100644 index 0000000..e07cbbd --- /dev/null +++ b/src/demo.spec.ts @@ -0,0 +1,7 @@ +import { describe, it, expect } from 'vitest'; + +describe('sum test', () => { + it('adds 1 + 2 to equal 3', () => { + expect(1 + 2).toBe(3); + }); +}); diff --git a/src/lib/actions/draggable.ts b/src/lib/actions/draggable.ts new file mode 100644 index 0000000..636a280 --- /dev/null +++ b/src/lib/actions/draggable.ts @@ -0,0 +1,49 @@ +import { dndState } from '$lib/stores/dnd.svelte.js'; +import type { DragDropOptions } from '$lib/types/index.js'; + +export function draggable(node: HTMLElement, options: DragDropOptions) { + function handleDragStart(event: DragEvent) { + if (options.disabled) return; + + // Update state using assignment (Svelte 5 style) + dndState.isDragging = true; + dndState.draggedItem = options.dragData; + dndState.sourceContainer = options.container; + dndState.targetContainer = null; + + if (event.dataTransfer) { + event.dataTransfer.effectAllowed = 'move'; + event.dataTransfer.setData('text/plain', JSON.stringify(options.dragData)); + } + + node.classList.add('dragging'); + options.callbacks?.onDragStart?.(dndState); + } + + function handleDragEnd() { + node.classList.remove('dragging'); + options.callbacks?.onDragEnd?.(dndState); + + // Reset state + dndState.isDragging = false; + dndState.draggedItem = null; + dndState.sourceContainer = ''; + dndState.targetContainer = null; + } + + node.draggable = !options.disabled; + node.addEventListener('dragstart', handleDragStart); + node.addEventListener('dragend', handleDragEnd); + + return { + update(newOptions: DragDropOptions) { + options = newOptions; + node.draggable = !options.disabled; + }, + + destroy() { + node.removeEventListener('dragstart', handleDragStart); + node.removeEventListener('dragend', handleDragEnd); + } + }; +} diff --git a/src/lib/actions/droppable.ts b/src/lib/actions/droppable.ts new file mode 100644 index 0000000..132b40a --- /dev/null +++ b/src/lib/actions/droppable.ts @@ -0,0 +1,71 @@ +import { dndState } from '$lib/stores/dnd.svelte.js'; +import type { DragDropOptions } from '$lib/types/index.js'; + +export function droppable(node: HTMLElement, options: DragDropOptions) { + function handleDragEnter(event: DragEvent) { + if (options.disabled) return; + event.preventDefault(); + + dndState.targetContainer = options.container; + node.classList.add('drag-over'); + options.callbacks?.onDragEnter?.(dndState); + } + + function handleDragLeave(event: DragEvent) { + if (options.disabled) return; + + const target = event.target as HTMLElement; + if (!node.contains(target)) { + dndState.targetContainer = null; + node.classList.remove('drag-over'); + options.callbacks?.onDragLeave?.(dndState); + } + } + + function handleDragOver(event: DragEvent) { + if (options.disabled) return; + event.preventDefault(); + + if (event.dataTransfer) { + event.dataTransfer.dropEffect = 'move'; + } + + options.callbacks?.onDragOver?.(dndState); + } + + async function handleDrop(event: DragEvent) { + if (options.disabled) return; + event.preventDefault(); + + node.classList.remove('drag-over'); + + try { + if (event.dataTransfer) { + const dragData = JSON.parse(event.dataTransfer.getData('text/plain')); + dndState.draggedItem = dragData; + } + + await options.callbacks?.onDrop?.(dndState); + } catch (error) { + console.error('Drop handling failed:', error); + } + } + + node.addEventListener('dragenter', handleDragEnter); + node.addEventListener('dragleave', handleDragLeave); + node.addEventListener('dragover', handleDragOver); + node.addEventListener('drop', handleDrop); + + return { + update(newOptions: DragDropOptions) { + options = newOptions; + }, + + destroy() { + node.removeEventListener('dragenter', handleDragEnter); + node.removeEventListener('dragleave', handleDragLeave); + node.removeEventListener('dragover', handleDragOver); + node.removeEventListener('drop', handleDrop); + } + }; +} diff --git a/src/lib/actions/index.ts b/src/lib/actions/index.ts new file mode 100644 index 0000000..10edd50 --- /dev/null +++ b/src/lib/actions/index.ts @@ -0,0 +1,2 @@ +export { draggable } from './draggable.js'; +export { droppable } from './droppable.js'; diff --git a/src/lib/index.ts b/src/lib/index.ts new file mode 100644 index 0000000..c9450e3 --- /dev/null +++ b/src/lib/index.ts @@ -0,0 +1,11 @@ +// Actions +export { draggable, droppable } from './actions/index.js'; + +// Store +export { dndState } from './stores/dnd.svelte.js'; + +// Types +export type * from './types/index.js'; + +// Styles +import './styles/dnd.css'; diff --git a/src/lib/stores/dnd.svelte.ts b/src/lib/stores/dnd.svelte.ts new file mode 100644 index 0000000..4bb7456 --- /dev/null +++ b/src/lib/stores/dnd.svelte.ts @@ -0,0 +1,9 @@ +import type { DragDropState } from '$lib/types/index.js'; + +// Global DnD state using Svelte 5's state rune +export const dndState = $state({ + isDragging: false, + draggedItem: null, + sourceContainer: '', + targetContainer: null +}); diff --git a/src/lib/styles/dnd.css b/src/lib/styles/dnd.css new file mode 100644 index 0000000..790b2be --- /dev/null +++ b/src/lib/styles/dnd.css @@ -0,0 +1,37 @@ +/* Base draggable styles */ +.svelte-dnd-draggable { + touch-action: none; /* Prevents touch scrolling while dragging */ + user-select: none; /* Prevents text selection during drag */ +} + +/* Active dragging state */ +.svelte-dnd-dragging { + opacity: 0.5; + cursor: grabbing; +} + +/* Draggable hover state */ +.svelte-dnd-draggable:hover { + cursor: grab; +} + +/* Droppable area styles */ +.svelte-dnd-droppable { + position: relative; +} + +/* Active drop target */ +.svelte-dnd-drop-target { + outline: 2px dashed #4caf50; +} + +/* Invalid drop target */ +.svelte-dnd-invalid-target { + outline: 2px dashed #f44336; +} + +/* Drop preview/placeholder */ +.svelte-dnd-placeholder { + opacity: 0.3; + border: 2px dashed #9e9e9e; +} diff --git a/src/lib/types/index.ts b/src/lib/types/index.ts new file mode 100644 index 0000000..6810d40 --- /dev/null +++ b/src/lib/types/index.ts @@ -0,0 +1,22 @@ +export interface DragDropState { + isDragging: boolean; + draggedItem: any; + sourceContainer: string; + targetContainer: string | null; +} + +export interface DragDropCallbacks { + onDragStart?: (state: DragDropState) => void; + onDragEnter?: (state: DragDropState) => void; + onDragLeave?: (state: DragDropState) => void; + onDragOver?: (state: DragDropState) => void; + onDrop?: (state: DragDropState) => Promise | void; + onDragEnd?: (state: DragDropState) => void; +} + +export interface DragDropOptions { + dragData?: any; + container: string; + disabled?: boolean; + callbacks?: DragDropCallbacks; +} diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte new file mode 100644 index 0000000..33ddc16 --- /dev/null +++ b/src/routes/+layout.svelte @@ -0,0 +1,60 @@ + + +
    +
    + + {@render children()} + +
    +
    diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte new file mode 100644 index 0000000..c5d6df7 --- /dev/null +++ b/src/routes/+page.svelte @@ -0,0 +1,153 @@ + + +
    +
    +

    Kanban Board

    +

    Drag and drop tasks between columns to reorder them in the board.

    +
    + +
    + {#each tasksByStatus as { status, items }} +
    +
    +
    +

    + {status.replace('-', ' ')} +

    + + {items.length} + +
    + +
    + {#each items as task (task.id)} +
    +
    +

    + {task.title} +

    + + {task.priority} + +
    +

    + {task.description} +

    +
    + {/each} +
    +
    +
    + {/each} +
    +
    + + diff --git a/src/routes/grid-sort/+page.svelte b/src/routes/grid-sort/+page.svelte new file mode 100644 index 0000000..8d097ed --- /dev/null +++ b/src/routes/grid-sort/+page.svelte @@ -0,0 +1,58 @@ + + +
    +
    +
    +

    Sortable List

    +

    Drag and drop items to reorder them in the list.

    +
    + +
    + {#each cards as card, index (card.id)} +
    +
    +
    + {card.icon} +
    +
    +
    + Position {index + 1} +
    +
    {/each} +
    +
    +
    diff --git a/src/routes/horizontal-scroll/+page.svelte b/src/routes/horizontal-scroll/+page.svelte new file mode 100644 index 0000000..199856b --- /dev/null +++ b/src/routes/horizontal-scroll/+page.svelte @@ -0,0 +1,60 @@ + + +
    +
    +

    Horizontal Image Gallery

    +

    Drag and drop images to rearrange them in the gallery.

    +
    + +
    + {#each images as image, index (image.id)} +
    +
    + + +
    + + +
    + {index + 1} +
    +
    + {/each} +
    +
    diff --git a/src/routes/nested/+page.svelte b/src/routes/nested/+page.svelte new file mode 100644 index 0000000..d516678 --- /dev/null +++ b/src/routes/nested/+page.svelte @@ -0,0 +1,188 @@ + + +
    +

    Nested Containers

    + +
    + {#each groups as group, groupIndex (group.id)} +
    +
    + +
    +
    +

    {group.title}

    +

    {group.description}

    +
    + + {group.items.length} + +
    + + +
    + {#each group.items as item, itemIndex (item.id)} +
    handleItemDrop(group.id, state) + } + }} + > +
    +
    +

    {item.title}

    + + {item.priority} + +
    +

    {item.description}

    +
    +
    + {/each} +
    +
    +
    + {/each} +
    +
    + + diff --git a/src/routes/simple-list/+page.svelte b/src/routes/simple-list/+page.svelte new file mode 100644 index 0000000..4ae1274 --- /dev/null +++ b/src/routes/simple-list/+page.svelte @@ -0,0 +1,105 @@ + + +
    +
    +

    Sortable List

    +

    Drag and drop items to reorder them in the list.

    +
    + +
    +
    +
    + {#each items as item, index (item.id)} +
    +
    +

    + {item.title} +

    + + {item.priority} + +
    +

    + {item.description} +

    +
    + {/each} +
    +
    +
    +
    + + diff --git a/static/favicon.png b/static/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..825b9e65af7c104cfb07089bb28659393b4f2097 GIT binary patch literal 1571 zcmV+;2Hg3HP)Px)-AP12RCwC$UE6KzI1p6{F2N z1VK2vi|pOpn{~#djwYcWXTI_im_u^TJgMZ4JMOsSj!0ma>B?-(Hr@X&W@|R-$}W@Z zgj#$x=!~7LGqHW?IO8+*oE1MyDp!G=L0#^lUx?;!fXv@l^6SvTnf^ac{5OurzC#ZMYc20lI%HhX816AYVs1T3heS1*WaWH z%;x>)-J}YB5#CLzU@GBR6sXYrD>Vw(Fmt#|JP;+}<#6b63Ike{Fuo!?M{yEffez;| zp!PfsuaC)>h>-AdbnwN13g*1LowNjT5?+lFVd#9$!8Z9HA|$*6dQ8EHLu}U|obW6f z2%uGv?vr=KNq7YYa2Roj;|zooo<)lf=&2yxM@e`kM$CmCR#x>gI>I|*Ubr({5Y^rb zghxQU22N}F51}^yfDSt786oMTc!W&V;d?76)9KXX1 z+6Okem(d}YXmmOiZq$!IPk5t8nnS{%?+vDFz3BevmFNgpIod~R{>@#@5x9zJKEHLHv!gHeK~n)Ld!M8DB|Kfe%~123&Hz1Z(86nU7*G5chmyDe ziV7$pB7pJ=96hpxHv9rCR29%bLOXlKU<_13_M8x)6;P8E1Kz6G<&P?$P^%c!M5`2` zfY2zg;VK5~^>TJGQzc+33-n~gKt{{of8GzUkWmU110IgI0DLxRIM>0US|TsM=L|@F z0Bun8U!cRB7-2apz=y-7*UxOxz@Z0)@QM)9wSGki1AZ38ceG7Q72z5`i;i=J`ILzL z@iUO?SBBG-0cQuo+an4TsLy-g-x;8P4UVwk|D8{W@U1Zi z!M)+jqy@nQ$p?5tsHp-6J304Q={v-B>66$P0IDx&YT(`IcZ~bZfmn11#rXd7<5s}y zBi9eim&zQc0Dk|2>$bs0PnLmDfMP5lcXRY&cvJ=zKxI^f0%-d$tD!`LBf9^jMSYUA zI8U?CWdY@}cRq6{5~y+)#h1!*-HcGW@+gZ4B};0OnC~`xQOyH19z*TA!!BJ%9s0V3F?CAJ{hTd#*tf+ur-W9MOURF-@B77_-OshsY}6 zOXRY=5%C^*26z?l)1=$bz30!so5tfABdSYzO+H=CpV~aaUefmjvfZ3Ttu9W&W3Iu6 zROlh0MFA5h;my}8lB0tAV-Rvc2Zs_CCSJnx@d`**$idgy-iMob4dJWWw|21b4NB=LfsYp0Aeh{Ov)yztQi;eL4y5 zMi>8^SzKqk8~k?UiQK^^-5d8c%bV?$F8%X~czyiaKCI2=UH