Compare commits
10 Commits
63fa164db7
...
d9974a3288
Author | SHA1 | Date |
---|---|---|
Emi Simpson | d9974a3288 | |
Emi Simpson | bc7227c5bd | |
Emi Simpson | 5e89527a0d | |
Emi Simpson | 1685ffc736 | |
Emi Simpson | 275c1e45a1 | |
Emi Simpson | 3c6ad85b77 | |
Emi Simpson | 9e2bd85175 | |
Emi Simpson | d3fd2f68c8 | |
Emi Simpson | ca82750003 | |
Emi Simpson | f66ea690a8 |
9
elm.json
9
elm.json
|
@ -6,6 +6,7 @@
|
|||
"elm-version": "0.19.1",
|
||||
"dependencies": {
|
||||
"direct": {
|
||||
"chelovek0v/bbase64": "1.0.1",
|
||||
"elm/browser": "1.0.2",
|
||||
"elm/core": "1.0.5",
|
||||
"elm/html": "1.0.0",
|
||||
|
@ -14,13 +15,17 @@
|
|||
"elm/url": "1.0.0",
|
||||
"elm-community/array-extra": "2.6.0",
|
||||
"elm-community/html-extra": "3.4.0",
|
||||
"elm-community/list-extra": "8.7.0",
|
||||
"elm-community/maybe-extra": "5.3.0",
|
||||
"elm-community/string-extra": "4.0.1"
|
||||
"elm-community/string-extra": "4.0.1",
|
||||
"elm-toulouse/cbor": "1.1.0"
|
||||
},
|
||||
"indirect": {
|
||||
"elm/bytes": "1.0.8",
|
||||
"elm/regex": "1.0.0",
|
||||
"elm/time": "1.0.0",
|
||||
"elm/virtual-dom": "1.0.3"
|
||||
"elm/virtual-dom": "1.0.3",
|
||||
"elm-toulouse/float16": "1.0.1"
|
||||
}
|
||||
},
|
||||
"test-dependencies": {
|
||||
|
|
202
src/Main.elm
202
src/Main.elm
|
@ -1,24 +1,34 @@
|
|||
module Main exposing (main)
|
||||
|
||||
import FunkyFunktions exposing (..)
|
||||
import Presets exposing (activities)
|
||||
import Stickers exposing (Sticker, StickerContent(..), viewSticker)
|
||||
|
||||
import Array exposing (Array, get, set)
|
||||
import Array.Extra as Array
|
||||
import Base64.Encode as B64E
|
||||
import Base64.Decode as B64D
|
||||
import Browser
|
||||
import Browser.Dom exposing (focus, getViewport, Viewport)
|
||||
import Browser.Navigation exposing (Key)
|
||||
import Browser.Navigation exposing (Key, pushUrl)
|
||||
import Browser.Events exposing (onMouseMove, onMouseUp, onResize)
|
||||
import Cbor exposing (CborItem(..))
|
||||
import Cbor.Encode as CE
|
||||
import Cbor.Decode as CD
|
||||
import Html exposing (Attribute, button, div, h3, input, Html, section, text)
|
||||
import Html.Attributes exposing (class, id, style, value)
|
||||
import Html.Attributes exposing (class, disabled, id, style, value)
|
||||
import Html.Attributes.Extra as Attributes exposing (attributeIf)
|
||||
import Html.Extra exposing (viewMaybe)
|
||||
import Html.Events exposing (onBlur, onClick, onInput, onMouseDown, onMouseEnter)
|
||||
import Html.Lazy exposing (lazy2)
|
||||
import Html.Events exposing (onBlur, onClick, onInput, onMouseDown, onMouseEnter, onMouseLeave)
|
||||
import Html.Events.Extra exposing (onEnter)
|
||||
import Html.Lazy exposing (lazy, lazy2)
|
||||
import Json.Decode as D
|
||||
import List exposing (map, singleton)
|
||||
import List.Extra exposing (elemIndex, getAt)
|
||||
import Maybe exposing (andThen)
|
||||
import Maybe.Extra exposing (isJust)
|
||||
import String exposing (fromInt, isEmpty)
|
||||
import Result exposing (toMaybe)
|
||||
import String exposing (dropLeft, fromInt, isEmpty, replace, toLower)
|
||||
import String.Extra exposing (isBlank)
|
||||
import Svg exposing (path, Svg, svg)
|
||||
import Svg.Attributes exposing (d, fill, height, stroke, viewBox, width)
|
||||
|
@ -40,7 +50,7 @@ type Msg
|
|||
| Click Int Int Int Int
|
||||
| SetTileText Int Int String
|
||||
| AddTile Int
|
||||
| TileDeselected Int
|
||||
| PruneTile Int Int
|
||||
| HeldOverNewTile Int Int
|
||||
| NewMousePos Int Int
|
||||
| StartDrag Int Int Tile Int Int
|
||||
|
@ -50,12 +60,10 @@ type alias Model =
|
|||
{ columns: Array Column
|
||||
, heldTile: Maybe HeldTile
|
||||
, mousePos: (Int, Int)
|
||||
, browserKey: Key
|
||||
}
|
||||
|
||||
type alias Column =
|
||||
{ name: String
|
||||
, tiles: Array Tile
|
||||
}
|
||||
type alias Column = { tiles: Array Tile }
|
||||
|
||||
type alias Tile =
|
||||
{ text: String
|
||||
|
@ -72,25 +80,17 @@ blankTile = { text = "", stickers = [] }
|
|||
|
||||
init : () -> Url -> Key -> (Model, Cmd Msg)
|
||||
init flags url browserKey =
|
||||
{ columns =
|
||||
[ { name = "Into"
|
||||
, tiles = Array.empty
|
||||
}
|
||||
, { name = "Willing"
|
||||
, tiles = Array.empty
|
||||
}
|
||||
, { name = "Maybe"
|
||||
, tiles = Array.empty
|
||||
}
|
||||
, { name = "No"
|
||||
, tiles = Array.empty
|
||||
}
|
||||
]
|
||||
|> Array.fromList
|
||||
, mousePos = (200, 200)
|
||||
, heldTile = Nothing
|
||||
}
|
||||
|> withoutCmd
|
||||
let
|
||||
m =
|
||||
case load browserKey url of
|
||||
Just model -> model
|
||||
Nothing ->
|
||||
{ columns = Array.repeat 4 (Column Array.empty)
|
||||
, mousePos = (200, 200)
|
||||
, heldTile = Nothing
|
||||
, browserKey = browserKey
|
||||
}
|
||||
in m |> withoutCmd
|
||||
|
||||
subscriptions : Model -> Sub Msg
|
||||
subscriptions model =
|
||||
|
@ -109,6 +109,7 @@ subscriptions model =
|
|||
view : Model -> Browser.Document Msg
|
||||
view {columns, heldTile, mousePos} =
|
||||
[ lazy2 viewColumns heldTile columns
|
||||
, lazy viewWordbank activities
|
||||
, viewMaybe (viewFloatyTile mousePos) heldTile
|
||||
]
|
||||
|> Browser.Document "meow!"
|
||||
|
@ -116,11 +117,10 @@ view {columns, heldTile, mousePos} =
|
|||
viewColumns : Maybe HeldTile -> Array Column -> Html Msg
|
||||
viewColumns heldTile columns =
|
||||
Array.indexedMap (viewColumn heldTile) columns
|
||||
|> Array.map (singleton >> div [])
|
||||
|> Array.toList
|
||||
|> section
|
||||
[ class "columns"
|
||||
-- Temporary hack while firefox's :has() selector is broken
|
||||
, attributeIf (isJust heldTile) <| style "user-select" "none"
|
||||
]
|
||||
|
||||
|
||||
|
@ -138,7 +138,7 @@ viewFloatyTile (mouseX, mouseY) { tile, hoveredColumnIndex } =
|
|||
viewHoverTile = div [id "hover-tile"] []
|
||||
|
||||
viewColumn : Maybe HeldTile -> Int -> Column -> Html Msg
|
||||
viewColumn heldOverTile columnIndex {name, tiles} =
|
||||
viewColumn heldOverTile columnIndex {tiles} =
|
||||
let
|
||||
isTileHeld = isJust heldOverTile
|
||||
tileCount = Array.length tiles
|
||||
|
@ -157,14 +157,23 @@ viewColumn heldOverTile columnIndex {name, tiles} =
|
|||
in
|
||||
div
|
||||
[ class "column"
|
||||
, attributeIf isTileHeld (onMouseLeave <| HeldOverNewTile -1 -1)
|
||||
]
|
||||
( ( h3
|
||||
[]
|
||||
[text name]
|
||||
[text <| columnIndexToName columnIndex]
|
||||
) :: tilesList
|
||||
++ [ viewAddTile isTileHeld columnIndex tileCount ]
|
||||
)
|
||||
|
||||
columnIndexToName : Int -> String
|
||||
columnIndexToName i = case i of
|
||||
0 -> "Into"
|
||||
1 -> "Willing"
|
||||
2 -> "Maybe"
|
||||
3 -> "No"
|
||||
_ -> "Too Many Columns"
|
||||
|
||||
viewTile : Bool -> Int -> Int -> Tile -> Html Msg
|
||||
viewTile isTileHeld columnIndex tileIndex tile =
|
||||
div
|
||||
|
@ -176,29 +185,30 @@ viewTile isTileHeld columnIndex tileIndex tile =
|
|||
-- )
|
||||
, attributeIf isTileHeld (onMouseEnter <| HeldOverNewTile columnIndex tileIndex)
|
||||
]
|
||||
[ viewGrip columnIndex tileIndex tile
|
||||
[ viewGrip 24 columnIndex tileIndex tile
|
||||
, input
|
||||
[ value tile.text
|
||||
, onInput (SetTileText columnIndex tileIndex)
|
||||
, onBlur (TileDeselected columnIndex)
|
||||
, attributeIf (isBlank tile.text) <| onBlur (PruneTile columnIndex tileIndex)
|
||||
, attributeIf (isBlank tile.text) (id "new-tile")
|
||||
, onEnter (AddTile columnIndex)
|
||||
]
|
||||
[]
|
||||
, svg
|
||||
[ Svg.Attributes.class "tile-stickers"
|
||||
, height "80"
|
||||
, width "400"
|
||||
, height "64"
|
||||
, width "320"
|
||||
, style "user-select" "none"
|
||||
]
|
||||
(map viewSticker tile.stickers)
|
||||
]
|
||||
|
||||
viewGrip : Int -> Int -> Tile -> Html Msg
|
||||
viewGrip colIndx tileIndx tile =
|
||||
viewGrip : Int -> Int -> Int -> Tile -> Html Msg
|
||||
viewGrip size colIndx tileIndx tile =
|
||||
svg
|
||||
[ viewBox "0 0 103.4 103.4"
|
||||
, width "30"
|
||||
, height "30"
|
||||
, width <| String.fromInt size
|
||||
, height <| String.fromInt size
|
||||
, Svg.Attributes.class "drag-gripper"
|
||||
, on "mousedown" <| (
|
||||
D.map2 (StartDrag colIndx tileIndx tile)
|
||||
|
@ -226,6 +236,27 @@ viewAddTile isTileHeld columnIndex tileCount =
|
|||
]
|
||||
[ text "+" ]
|
||||
|
||||
viewWordbank : List String -> Html Msg
|
||||
viewWordbank wordlist =
|
||||
section
|
||||
[ id "word-bank"
|
||||
]
|
||||
(map viewMiniTile wordlist)
|
||||
|
||||
viewMiniTile : String -> Html Msg
|
||||
viewMiniTile word =
|
||||
div
|
||||
[ class "tile"
|
||||
, class "mini-tile"
|
||||
]
|
||||
[ viewGrip 16 -1 -1 { text = word, stickers = [] }
|
||||
, input
|
||||
[ value word
|
||||
, disabled True
|
||||
]
|
||||
[]
|
||||
]
|
||||
|
||||
addStickerToTile : Sticker -> Tile -> Tile
|
||||
addStickerToTile sticker tile =
|
||||
{ tile | stickers = sticker :: tile.stickers }
|
||||
|
@ -237,10 +268,6 @@ addTileToColumn column =
|
|||
isTileEmpty : Tile -> Bool
|
||||
isTileEmpty = .text >> isEmpty
|
||||
|
||||
pruneTiles : Column -> Column
|
||||
pruneTiles column =
|
||||
{ column | tiles = Array.filter (not << isTileEmpty) column.tiles }
|
||||
|
||||
updateTileText : String -> Tile -> Tile
|
||||
updateTileText text tile =
|
||||
{ tile | text = text }
|
||||
|
@ -292,17 +319,17 @@ update msg model = case Debug.log "UPDATE" msg of
|
|||
(modColumnInPage columnIndex << modTileInColumn tileIndex)
|
||||
(updateTileText newText)
|
||||
model
|
||||
|> withoutCmd
|
||||
|> withSaveCmd
|
||||
AddTile columnIndex ->
|
||||
modColumnInPage columnIndex
|
||||
addTileToColumn
|
||||
model
|
||||
|> withCmd (Task.attempt (constant Noop) (focus "new-tile"))
|
||||
TileDeselected columnIndex ->
|
||||
PruneTile columnIndex tileIndex ->
|
||||
modColumnInPage columnIndex
|
||||
pruneTiles
|
||||
(removeTileFromColumn tileIndex)
|
||||
model
|
||||
|> withoutCmd
|
||||
|> withSaveCmd
|
||||
HeldOverNewTile columnIndex tileIndex -> case model.heldTile of
|
||||
Nothing -> model |> withoutCmd
|
||||
Just oldHeldTileInfo ->
|
||||
|
@ -353,4 +380,79 @@ update msg model = case Debug.log "UPDATE" msg of
|
|||
model
|
||||
in
|
||||
{ modelWithTileInserted | heldTile = Nothing }
|
||||
|> withoutCmd
|
||||
|> withSaveCmd
|
||||
|
||||
withSaveCmd : Model -> (Model, Cmd Msg)
|
||||
withSaveCmd model = (model, save model)
|
||||
|
||||
andSaveCmd : (Model, Cmd Msg) -> (Model, Cmd Msg)
|
||||
andSaveCmd (model, cmd) = (model, Cmd.batch [cmd, save model])
|
||||
|
||||
save : Model -> Cmd Msg
|
||||
save model =
|
||||
saveModel model
|
||||
|> CE.encode
|
||||
|> B64E.bytes
|
||||
|> B64E.encode
|
||||
|> dropLeft 1
|
||||
|> replace "=" ""
|
||||
|> (++) "#"
|
||||
|> pushUrl model.browserKey
|
||||
|
||||
load : Key -> Url -> Maybe Model
|
||||
load key url =
|
||||
url.fragment
|
||||
|> Maybe.map ((++) "g")
|
||||
|> andThen (B64D.decode B64D.bytes >> toMaybe)
|
||||
|> andThen (CD.decode (loadModel key))
|
||||
|
||||
|
||||
saveModel : Model -> CE.Encoder
|
||||
saveModel { columns } =
|
||||
Array.toList columns
|
||||
|> map saveColumn
|
||||
|> CE.sequence
|
||||
|
||||
array4 a b c d = Array.fromList [a, b, c, d]
|
||||
|
||||
loadModel : Key -> CD.Decoder Model
|
||||
loadModel key =
|
||||
CD.map4 array4 loadColumn loadColumn loadColumn loadColumn
|
||||
|> CD.map Model
|
||||
|> CD.map ((|>) Nothing)
|
||||
|> CD.map ((|>) (0, 0))
|
||||
|> CD.map ((|>) key)
|
||||
|
||||
saveColumn : Column -> CE.Encoder
|
||||
saveColumn { tiles } = CE.list saveTile (Array.toList tiles)
|
||||
|
||||
loadColumn : CD.Decoder Column
|
||||
loadColumn =
|
||||
CD.list loadTile
|
||||
|> CD.map Array.fromList
|
||||
|> CD.map Column
|
||||
|
||||
saveTile : Tile -> CE.Encoder
|
||||
saveTile { text } =
|
||||
case elemIndex (toLower text) activities of
|
||||
Just index -> CE.int index
|
||||
Nothing -> CE.string text
|
||||
|
||||
loadTile : CD.Decoder Tile
|
||||
loadTile =
|
||||
CD.any
|
||||
|> CD.andThen loadTileInner
|
||||
|
||||
loadTileInner : CborItem -> CD.Decoder Tile
|
||||
loadTileInner item =
|
||||
let
|
||||
word =
|
||||
case item of
|
||||
CborInt i ->
|
||||
case getAt i activities of
|
||||
Just activity -> CD.succeed activity
|
||||
Nothing -> CD.fail
|
||||
CborString s -> CD.succeed s
|
||||
_ -> CD.fail
|
||||
in
|
||||
CD.map (flip Tile []) word
|
777
src/Presets.elm
777
src/Presets.elm
|
@ -9,411 +9,390 @@ type alias WordSet =
|
|||
, words : List String -- e.g. Bondage, Schlong, Loss of Control
|
||||
}
|
||||
|
||||
allWordSets = [activitiesSet, languageSet, feelingsSet]
|
||||
|
||||
activitiesSet = WordSet
|
||||
"Activities"
|
||||
(["Yes - Into", "Yes - Willing", "Maybe", "No"] |> StickerContent "black")
|
||||
-- TODO make actual stickers for these
|
||||
(["Top / Giver", "Bottom / Reciever", "Never Tried", "Favorite"] |> StickerContent "black")
|
||||
activities
|
||||
|
||||
languageSet = WordSet
|
||||
"Language"
|
||||
(["Yes - Into", "Yes - Willing", "Maybe", "No"] |> StickerContent "black")
|
||||
(["Speaker", "Listener", "Never Tried", "Favorite"] |> StickerContent "black")
|
||||
language
|
||||
|
||||
feelingsSet = WordSet
|
||||
"Feelings"
|
||||
(["Often", "Sometimes", "Never"] |> StickerContent "black")
|
||||
(["I like to feel", "I want my partner to feel", "Never Tried", "Favorite"] |> StickerContent "black")
|
||||
|
||||
|
||||
activities =
|
||||
[ "69"
|
||||
, "Age-Play"
|
||||
, "Anal Sex"
|
||||
, "Analingus/Rimming"
|
||||
, "Ball Stretching"
|
||||
, "Being Filmed/Photographed"
|
||||
, "Being Watched"
|
||||
, "Biting"
|
||||
, "Blindfolds"
|
||||
, "Blood Play"
|
||||
, "Light Bondage"
|
||||
, "Heavy Bondage"
|
||||
, "Rope"
|
||||
, "Boot-blacking"
|
||||
, "Bratting"
|
||||
, "Breath Play"
|
||||
, "Butt Plugs"
|
||||
, "Cages/Confinement"
|
||||
, "Caning"
|
||||
, "Chastity"
|
||||
, "Cock/Pussy Worship"
|
||||
, "Cockrings"
|
||||
, "Collars"
|
||||
, "Consensual Non-Consent"
|
||||
, "Costumes"
|
||||
, "Cross Dressing"
|
||||
, "Cuckolding"
|
||||
, "Cuddling"
|
||||
, "Cunnilingus"
|
||||
, "Degradation"
|
||||
, "Dirty Talk"
|
||||
, "Domination"
|
||||
, "Double Penetration" -- TODO Which hole(s)? note??? how do we handle this?
|
||||
, "E-Stim"
|
||||
, "Edging"
|
||||
, "Ejaculate"
|
||||
, "Enemas"
|
||||
, "Eye Contact (or restriction from)"
|
||||
, "Face Fucking"
|
||||
, "Facesitting"
|
||||
, "Fellatio"
|
||||
, "Fingering" -- (External? Anal? Vaginal?)
|
||||
, "Fisting" -- (Anal? Vaginal?)
|
||||
, "Flogging"
|
||||
, "Food Play"
|
||||
, "Foot Play"
|
||||
, "Frottage"
|
||||
, "Furries"
|
||||
, "G-Spot"
|
||||
, "Gags"
|
||||
, "Gender Play"
|
||||
, "Genital Torture"
|
||||
, "Group Sex"
|
||||
, "Hair Pulling"
|
||||
, "Hoods"
|
||||
, "Humiliation"
|
||||
, "Incest"
|
||||
, "Roleplay"
|
||||
, "Kicking"
|
||||
, "Kidnapping"
|
||||
, "Roleplay"
|
||||
, "Kissing" -- (Where?)
|
||||
, "Knife Play"
|
||||
, "Leather"
|
||||
, "Lingerie"
|
||||
, "Massage"
|
||||
, "Medical Play"
|
||||
, "Moans"
|
||||
, "Mutual Masturbation"
|
||||
, "Nipple Clamps"
|
||||
, "Nipple Play"
|
||||
, "Nipple Torture"
|
||||
, "Objectification"
|
||||
, "Orgasm Control"
|
||||
, "Orgasm Denial"
|
||||
, "Paddles"
|
||||
, "Mild Pain"
|
||||
, "Moderate Pain"
|
||||
, "Severe Pain"
|
||||
, "Pegging"
|
||||
, "Piercing"
|
||||
, "Phone Sex"
|
||||
, "Piss Play"
|
||||
, "Porn"
|
||||
, "Power Exchange"
|
||||
, "Prostate Play"
|
||||
, "Punching"
|
||||
, "Punishment"
|
||||
, "Race Play"
|
||||
, "Riding Crops"
|
||||
, "Role Play" -- (Which Roles?)
|
||||
, "Rubber/Latex Clothing"
|
||||
, "Scat"
|
||||
, "Scratching"
|
||||
, "Sensory Deprivation"
|
||||
, "Service"
|
||||
, "Sex During Menstruation"
|
||||
, "Sex in Public"
|
||||
, "Sex Magic"
|
||||
, "Sex Parties"
|
||||
, "Sex Toys"
|
||||
, "Sexting"
|
||||
, "Shaving"
|
||||
, "Slapping" -- (Where?)
|
||||
, "Smoking" -- (Cigarettes? 420? Cigars?)
|
||||
, "Spanking"
|
||||
, "Sploshing"
|
||||
, "Spreader Bars"
|
||||
, "Strap Ons"
|
||||
, "Strip Clubs"
|
||||
, "Submission"
|
||||
, "Suspension"
|
||||
, "Swallowing Ejaculate"
|
||||
, "Tantra"
|
||||
, "Teasing"
|
||||
, "Temporary Marks"
|
||||
, "Threesome" -- (Genders?)
|
||||
, "Tickling"
|
||||
, "Tit-Fucking"
|
||||
, "Tribadism"
|
||||
, "Triple Penetration"
|
||||
, "Vaginal Penetration"
|
||||
, "Watching Others"
|
||||
, "Wax"
|
||||
, "Whips"
|
||||
, "Wrestling"
|
||||
, "age-play"
|
||||
, "anal sex"
|
||||
, "analingus/rimming"
|
||||
, "ball stretching"
|
||||
, "being filmed/photographed"
|
||||
, "being watched"
|
||||
, "biting"
|
||||
, "blindfolds"
|
||||
, "blood play"
|
||||
, "light bondage"
|
||||
, "heavy bondage"
|
||||
, "rope"
|
||||
, "boot-blacking"
|
||||
, "bratting"
|
||||
, "breath play"
|
||||
, "butt plugs"
|
||||
, "cages/confinement"
|
||||
, "caning"
|
||||
, "chastity"
|
||||
, "cock/pussy worship"
|
||||
, "cockrings"
|
||||
, "collars"
|
||||
, "consensual non-consent"
|
||||
, "costumes"
|
||||
, "cross dressing"
|
||||
, "cuckolding"
|
||||
, "cuddling"
|
||||
, "cunnilingus"
|
||||
, "degradation"
|
||||
, "dirty talk"
|
||||
, "domination"
|
||||
, "double penetration" -- todo which hole(s)? note??? how do we handle this?
|
||||
, "e-stim"
|
||||
, "edging"
|
||||
, "ejaculate"
|
||||
, "enemas"
|
||||
, "eye contact (or restriction from)"
|
||||
, "face fucking"
|
||||
, "facesitting"
|
||||
, "fellatio"
|
||||
, "fingering" -- (external? anal? vaginal?)
|
||||
, "fisting" -- (anal? vaginal?)
|
||||
, "flogging"
|
||||
, "food play"
|
||||
, "foot play"
|
||||
, "frottage"
|
||||
, "furries"
|
||||
, "g-spot"
|
||||
, "gags"
|
||||
, "gender play"
|
||||
, "genital torture"
|
||||
, "group sex"
|
||||
, "hair pulling"
|
||||
, "hoods"
|
||||
, "humiliation"
|
||||
, "incest"
|
||||
, "roleplay"
|
||||
, "kicking"
|
||||
, "kidnapping"
|
||||
, "roleplay"
|
||||
, "kissing" -- (where?)
|
||||
, "knife play"
|
||||
, "leather"
|
||||
, "lingerie"
|
||||
, "massage"
|
||||
, "medical play"
|
||||
, "moans"
|
||||
, "mutual masturbation"
|
||||
, "nipple clamps"
|
||||
, "nipple play"
|
||||
, "nipple torture"
|
||||
, "objectification"
|
||||
, "orgasm control"
|
||||
, "orgasm denial"
|
||||
, "paddles"
|
||||
, "mild pain"
|
||||
, "moderate pain"
|
||||
, "severe pain"
|
||||
, "pegging"
|
||||
, "piercing"
|
||||
, "phone sex"
|
||||
, "piss play"
|
||||
, "porn"
|
||||
, "power exchange"
|
||||
, "prostate play"
|
||||
, "punching"
|
||||
, "punishment"
|
||||
, "race play"
|
||||
, "riding crops"
|
||||
, "role play" -- (which roles?)
|
||||
, "rubber/latex clothing"
|
||||
, "scat"
|
||||
, "scratching"
|
||||
, "sensory deprivation"
|
||||
, "service"
|
||||
, "sex during menstruation"
|
||||
, "sex in public"
|
||||
, "sex magic"
|
||||
, "sex parties"
|
||||
, "sex toys"
|
||||
, "sexting"
|
||||
, "shaving"
|
||||
, "slapping" -- (where?)
|
||||
, "smoking" -- (cigarettes? 420? cigars?)
|
||||
, "spanking"
|
||||
, "sploshing"
|
||||
, "spreader bars"
|
||||
, "strap ons"
|
||||
, "strip clubs"
|
||||
, "submission"
|
||||
, "suspension"
|
||||
, "swallowing ejaculate"
|
||||
, "tantra"
|
||||
, "teasing"
|
||||
, "temporary marks"
|
||||
, "threesome" -- (genders?)
|
||||
, "tickling"
|
||||
, "tit-fucking"
|
||||
, "tribadism"
|
||||
, "triple penetration"
|
||||
, "vaginal penetration"
|
||||
, "watching others"
|
||||
, "wax"
|
||||
, "whips"
|
||||
, "wrestling"
|
||||
]
|
||||
|
||||
language =
|
||||
[ "Abuse"
|
||||
, "Aching"
|
||||
, "Ample"
|
||||
, "Aroused"
|
||||
, "Ass"
|
||||
, "Asshole"
|
||||
, "Babe"
|
||||
, "Baby"
|
||||
, "Baby Girl/Boy"
|
||||
, "Balls"
|
||||
, "Bang"
|
||||
, "Beat"
|
||||
, "Beautiful"
|
||||
, "Beg"
|
||||
, "Bitch"
|
||||
, "Bite"
|
||||
, "Bits"
|
||||
, "Blowjob"
|
||||
, "Blush"
|
||||
, "Bone/Boner"
|
||||
, "Boobs"
|
||||
, "Booty"
|
||||
, "Bottom"
|
||||
, "Boy/Boi"
|
||||
, "Brat"
|
||||
, "Breasts"
|
||||
, "Bruise"
|
||||
, "Bulge"
|
||||
, "Blush"
|
||||
, "Butt"
|
||||
, "Button"
|
||||
, "Choke"
|
||||
, "Clit"
|
||||
, "Clitoris"
|
||||
, "Cock"
|
||||
, "Cock Sucking"
|
||||
, "Cum"
|
||||
, "Cum Dumpster"
|
||||
, "Cum Slut"
|
||||
, "Cunnilingus"
|
||||
, "Cunt"
|
||||
, "Daddy"
|
||||
, "Darling"
|
||||
, "Destroy"
|
||||
, "Dick"
|
||||
, "Dirty"
|
||||
, "Disappointment"
|
||||
, "Disgusting"
|
||||
, "“Down There”"
|
||||
, "Dripping"
|
||||
, "Eating Out"
|
||||
, "Embarrassed"
|
||||
, "Face Fucking"
|
||||
, "Faggot"
|
||||
, "Fap"
|
||||
, "Fellatio"
|
||||
, "Filthy"
|
||||
, "Finger"
|
||||
, "Finger Bang"
|
||||
, "Finger Fuck"
|
||||
, "Freak"
|
||||
, "Fuck"
|
||||
, "Fuck Toy"
|
||||
, "Gag"
|
||||
, "Giggle"
|
||||
, "Girl"
|
||||
, "Goddess"
|
||||
, "Gorgeous"
|
||||
, "Grab"
|
||||
, "Groan"
|
||||
, "Hairy"
|
||||
, "Hard/Hard On"
|
||||
, "Hole"
|
||||
, "Honey"
|
||||
, "Horny"
|
||||
, "Hot"
|
||||
, "Intense"
|
||||
, "Jerk Off"
|
||||
, "Jizz"
|
||||
, "Jugs"
|
||||
, "Juicy"
|
||||
, "Junk"
|
||||
, "Kitten"
|
||||
, "Lick"
|
||||
, "Lips"
|
||||
, "Little"
|
||||
, "Little One"
|
||||
, "Load"
|
||||
, "Ma’am"
|
||||
, "Master"
|
||||
, "Masturbate"
|
||||
, "Member"
|
||||
, "Mine"
|
||||
, "Miss"
|
||||
, "Mister"
|
||||
, "Mistress"
|
||||
, "Moan"
|
||||
, "Moist"
|
||||
, "Mouth"
|
||||
, "Nads"
|
||||
, "Nasty"
|
||||
, "Nipples"
|
||||
, "Pathetic"
|
||||
, "Pecker"
|
||||
, "Pervert"
|
||||
, "Pig/Piggy"
|
||||
, "Pink"
|
||||
, "Please"
|
||||
, "Pound"
|
||||
, "Prick"
|
||||
, "Princess"
|
||||
, "Property"
|
||||
, "Punch"
|
||||
, "Pup"
|
||||
, "Pussy"
|
||||
, "Rape"
|
||||
, "Ravage"
|
||||
, "Red"
|
||||
, "Rump"
|
||||
, "Sack"
|
||||
, "Sad"
|
||||
, "Schlong"
|
||||
, "Scratch"
|
||||
, "Scream"
|
||||
, "Screw"
|
||||
, "Sexy"
|
||||
, "Shiver"
|
||||
, "Shoot"
|
||||
, "Sir"
|
||||
, "Sissy"
|
||||
, "Skank"
|
||||
, "Slam"
|
||||
, "Slap"
|
||||
, "Slave"
|
||||
, "Slide"
|
||||
, "Slut"
|
||||
, "Smack"
|
||||
, "Smooth"
|
||||
, "Snatch"
|
||||
, "Soft"
|
||||
, "Solid"
|
||||
, "Spank"
|
||||
, "Spit"
|
||||
, "Squeeze"
|
||||
, "Strong"
|
||||
, "Stupid"
|
||||
, "Suck"
|
||||
, "Sweet"
|
||||
, "Sweetheart"
|
||||
, "Tease"
|
||||
, "Teeth"
|
||||
, "Tight"
|
||||
, "Tits"
|
||||
, "Top"
|
||||
, "Toy"
|
||||
, "Tramp"
|
||||
, "Turgid"
|
||||
, "Twat"
|
||||
, "Vag"
|
||||
, "Vagina"
|
||||
, "Vixen"
|
||||
, "Vulva"
|
||||
, "Wad"
|
||||
, "Wang"
|
||||
, "Wank"
|
||||
, "Watch"
|
||||
, "Wet"
|
||||
, "Whimper"
|
||||
, "Whore"
|
||||
, "Worthless"
|
||||
[ "abuse"
|
||||
, "aching"
|
||||
, "ample"
|
||||
, "aroused"
|
||||
, "ass"
|
||||
, "asshole"
|
||||
, "babe"
|
||||
, "baby"
|
||||
, "baby girl/boy"
|
||||
, "balls"
|
||||
, "bang"
|
||||
, "beat"
|
||||
, "beautiful"
|
||||
, "beg"
|
||||
, "bitch"
|
||||
, "bite"
|
||||
, "bits"
|
||||
, "blowjob"
|
||||
, "blush"
|
||||
, "bone/boner"
|
||||
, "boobs"
|
||||
, "booty"
|
||||
, "bottom"
|
||||
, "boy/boi"
|
||||
, "brat"
|
||||
, "breasts"
|
||||
, "bruise"
|
||||
, "bulge"
|
||||
, "blush"
|
||||
, "butt"
|
||||
, "button"
|
||||
, "choke"
|
||||
, "clit"
|
||||
, "clitoris"
|
||||
, "cock"
|
||||
, "cock sucking"
|
||||
, "cum"
|
||||
, "cum dumpster"
|
||||
, "cum slut"
|
||||
, "cunnilingus"
|
||||
, "cunt"
|
||||
, "daddy"
|
||||
, "darling"
|
||||
, "destroy"
|
||||
, "dick"
|
||||
, "dirty"
|
||||
, "disappointment"
|
||||
, "disgusting"
|
||||
, "“down there”"
|
||||
, "dripping"
|
||||
, "eating out"
|
||||
, "embarrassed"
|
||||
, "face fucking"
|
||||
, "faggot"
|
||||
, "fap"
|
||||
, "fellatio"
|
||||
, "filthy"
|
||||
, "finger"
|
||||
, "finger bang"
|
||||
, "finger fuck"
|
||||
, "freak"
|
||||
, "fuck"
|
||||
, "fuck toy"
|
||||
, "gag"
|
||||
, "giggle"
|
||||
, "girl"
|
||||
, "goddess"
|
||||
, "gorgeous"
|
||||
, "grab"
|
||||
, "groan"
|
||||
, "hairy"
|
||||
, "hard/hard on"
|
||||
, "hole"
|
||||
, "honey"
|
||||
, "horny"
|
||||
, "hot"
|
||||
, "intense"
|
||||
, "jerk off"
|
||||
, "jizz"
|
||||
, "jugs"
|
||||
, "juicy"
|
||||
, "junk"
|
||||
, "kitten"
|
||||
, "lick"
|
||||
, "lips"
|
||||
, "little"
|
||||
, "little one"
|
||||
, "load"
|
||||
, "ma’am"
|
||||
, "master"
|
||||
, "masturbate"
|
||||
, "member"
|
||||
, "mine"
|
||||
, "miss"
|
||||
, "mister"
|
||||
, "mistress"
|
||||
, "moan"
|
||||
, "moist"
|
||||
, "mouth"
|
||||
, "nads"
|
||||
, "nasty"
|
||||
, "nipples"
|
||||
, "pathetic"
|
||||
, "pecker"
|
||||
, "pervert"
|
||||
, "pig/piggy"
|
||||
, "pink"
|
||||
, "please"
|
||||
, "pound"
|
||||
, "prick"
|
||||
, "princess"
|
||||
, "property"
|
||||
, "punch"
|
||||
, "pup"
|
||||
, "pussy"
|
||||
, "rape"
|
||||
, "ravage"
|
||||
, "red"
|
||||
, "rump"
|
||||
, "sack"
|
||||
, "sad"
|
||||
, "schlong"
|
||||
, "scratch"
|
||||
, "scream"
|
||||
, "screw"
|
||||
, "sexy"
|
||||
, "shiver"
|
||||
, "shoot"
|
||||
, "sir"
|
||||
, "sissy"
|
||||
, "skank"
|
||||
, "slam"
|
||||
, "slap"
|
||||
, "slave"
|
||||
, "slide"
|
||||
, "slut"
|
||||
, "smack"
|
||||
, "smooth"
|
||||
, "snatch"
|
||||
, "soft"
|
||||
, "solid"
|
||||
, "spank"
|
||||
, "spit"
|
||||
, "squeeze"
|
||||
, "strong"
|
||||
, "stupid"
|
||||
, "suck"
|
||||
, "sweet"
|
||||
, "sweetheart"
|
||||
, "tease"
|
||||
, "teeth"
|
||||
, "tight"
|
||||
, "tits"
|
||||
, "top"
|
||||
, "toy"
|
||||
, "tramp"
|
||||
, "turgid"
|
||||
, "twat"
|
||||
, "vag"
|
||||
, "vagina"
|
||||
, "vixen"
|
||||
, "vulva"
|
||||
, "wad"
|
||||
, "wang"
|
||||
, "wank"
|
||||
, "watch"
|
||||
, "wet"
|
||||
, "whimper"
|
||||
, "whore"
|
||||
, "worthless"
|
||||
]
|
||||
|
||||
feelings =
|
||||
[ "Abandoned"
|
||||
, "Accomplished"
|
||||
, "Adored"
|
||||
, "Animalistic"
|
||||
, "Anger"
|
||||
, "Ashamed"
|
||||
, "Bad"
|
||||
, "Belonging"
|
||||
, "Big"
|
||||
, "Catharsis"
|
||||
, "Cherished"
|
||||
, "Clever"
|
||||
, "Coerced"
|
||||
, "Competent"
|
||||
, "Connected"
|
||||
, "Corrupted"
|
||||
, "Defeated"
|
||||
, "Desired"
|
||||
, "Dirty"
|
||||
, "Disrespected"
|
||||
, "Dutiful"
|
||||
, "Embarrassed"
|
||||
, "Encouraged"
|
||||
, "Euphoric"
|
||||
, "Fear"
|
||||
, "Focused"
|
||||
, "Forced"
|
||||
, "Forgiveness"
|
||||
, "Free"
|
||||
, "Good"
|
||||
, "Helplessness"
|
||||
, "Humiliation"
|
||||
, "Humility"
|
||||
, "Idolized"
|
||||
, "Impressed"
|
||||
, "Infantilized"
|
||||
, "Innocent"
|
||||
, "Loss of Control"
|
||||
, "Loved"
|
||||
, "Lust"
|
||||
, "Mean"
|
||||
, "Neediness"
|
||||
, "Nurturing"
|
||||
, "Objectified"
|
||||
, "Open"
|
||||
, "Out of Control"
|
||||
, "Overpowered"
|
||||
, "Overwhelmed"
|
||||
, "Owned"
|
||||
, "Passivity"
|
||||
, "Pathos"
|
||||
, "Perverted"
|
||||
, "Pity"
|
||||
, "Powerful"
|
||||
, "Protected"
|
||||
, "Punished"
|
||||
, "Rebellious"
|
||||
, "Rebellious"
|
||||
, "Redemption"
|
||||
, "Resentment"
|
||||
, "Redeemed"
|
||||
, "Resentment"
|
||||
, "Respected"
|
||||
, "Sadistic"
|
||||
, "Sadness"
|
||||
, "Safe"
|
||||
, "Satiated"
|
||||
, "Served"
|
||||
, "Sexy"
|
||||
, "Small"
|
||||
, "Special"
|
||||
, "Strong"
|
||||
, "Submissive"
|
||||
, "Subservient"
|
||||
, "Trust"
|
||||
, "Used"
|
||||
, "Useful"
|
||||
, "Victimized"
|
||||
, "Violated"
|
||||
, "Wanted"
|
||||
, "Worshiped"
|
||||
, "Worthless"
|
||||
, "Wrong"
|
||||
[ "abandoned"
|
||||
, "accomplished"
|
||||
, "adored"
|
||||
, "animalistic"
|
||||
, "anger"
|
||||
, "ashamed"
|
||||
, "bad"
|
||||
, "belonging"
|
||||
, "big"
|
||||
, "catharsis"
|
||||
, "cherished"
|
||||
, "clever"
|
||||
, "coerced"
|
||||
, "competent"
|
||||
, "connected"
|
||||
, "corrupted"
|
||||
, "defeated"
|
||||
, "desired"
|
||||
, "dirty"
|
||||
, "disrespected"
|
||||
, "dutiful"
|
||||
, "embarrassed"
|
||||
, "encouraged"
|
||||
, "euphoric"
|
||||
, "fear"
|
||||
, "focused"
|
||||
, "forced"
|
||||
, "forgiveness"
|
||||
, "free"
|
||||
, "good"
|
||||
, "helplessness"
|
||||
, "humiliation"
|
||||
, "humility"
|
||||
, "idolized"
|
||||
, "impressed"
|
||||
, "infantilized"
|
||||
, "innocent"
|
||||
, "loss of control"
|
||||
, "loved"
|
||||
, "lust"
|
||||
, "mean"
|
||||
, "neediness"
|
||||
, "nurturing"
|
||||
, "objectified"
|
||||
, "open"
|
||||
, "out of control"
|
||||
, "overpowered"
|
||||
, "overwhelmed"
|
||||
, "owned"
|
||||
, "passivity"
|
||||
, "pathos"
|
||||
, "perverted"
|
||||
, "pity"
|
||||
, "powerful"
|
||||
, "protected"
|
||||
, "punished"
|
||||
, "rebellious"
|
||||
, "rebellious"
|
||||
, "redemption"
|
||||
, "resentment"
|
||||
, "redeemed"
|
||||
, "resentment"
|
||||
, "respected"
|
||||
, "sadistic"
|
||||
, "sadness"
|
||||
, "safe"
|
||||
, "satiated"
|
||||
, "served"
|
||||
, "sexy"
|
||||
, "small"
|
||||
, "special"
|
||||
, "strong"
|
||||
, "submissive"
|
||||
, "subservient"
|
||||
, "trust"
|
||||
, "used"
|
||||
, "useful"
|
||||
, "victimized"
|
||||
, "violated"
|
||||
, "wanted"
|
||||
, "worshiped"
|
||||
, "worthless"
|
||||
, "wrong"
|
||||
]
|
130
style.sass
130
style.sass
|
@ -3,35 +3,38 @@ button
|
|||
|
||||
h3
|
||||
font-family: 'Rent Strike'
|
||||
font-size: 5em
|
||||
margin: 30px
|
||||
font-size: 4em
|
||||
margin: 24px
|
||||
|
||||
input
|
||||
font-family: 'Rent Strike'
|
||||
font-size: 1.5em
|
||||
font-size: 1.2em
|
||||
|
||||
.columns
|
||||
display: flex
|
||||
flex-flow: row wrap
|
||||
justify-content: center
|
||||
overflow-y: auto
|
||||
|
||||
& > :nth-child(4n+1)
|
||||
--color-strong: #c0d694
|
||||
--color-weak: #e5eed4
|
||||
|
||||
& > :nth-child(4n+2)
|
||||
--color-strong: #6ed8d6
|
||||
--color-weak: #d3f3f2
|
||||
|
||||
& > :nth-child(4n+3)
|
||||
--color-strong: #d3aee1
|
||||
--color-weak: #eddef3
|
||||
|
||||
& > :nth-child(4n+4)
|
||||
--color-strong: #eeab87
|
||||
--color-weak: #f9e5db
|
||||
|
||||
.column
|
||||
width: 400px
|
||||
padding: 20px
|
||||
|
||||
&:nth-child(4n+1)
|
||||
--color-strong: #c0d694
|
||||
--color-weak: #e5eed4
|
||||
|
||||
&:nth-child(4n+2)
|
||||
--color-strong: #6ed8d6
|
||||
--color-weak: #d3f3f2
|
||||
|
||||
&:nth-child(4n+3)
|
||||
--color-strong: #d3aee1
|
||||
--color-weak: #eddef3
|
||||
|
||||
&:nth-child(4n+4)
|
||||
--color-strong: #eeab87
|
||||
--color-weak: #f9e5db
|
||||
width: 320px
|
||||
padding: 64px
|
||||
|
||||
& > h3
|
||||
color: var(--color-strong)
|
||||
|
@ -42,46 +45,62 @@ input
|
|||
text-align: center
|
||||
|
||||
#hover-tile
|
||||
height: 110px
|
||||
margin-top: -15px
|
||||
height: 88px
|
||||
margin-top: -12px
|
||||
|
||||
.tile
|
||||
position: relative
|
||||
height: 80px
|
||||
width: 400px
|
||||
height: 64px
|
||||
width: 320px
|
||||
|
||||
display: grid
|
||||
align-items: center
|
||||
margin-bottom: 15px
|
||||
margin-bottom: 12px
|
||||
border: none
|
||||
background-color: var(--color-weak)
|
||||
|
||||
&.mini-tile
|
||||
height: 40px
|
||||
width: 200px
|
||||
margin: 10px
|
||||
|
||||
--color-strong: #999
|
||||
--color-weak: #ccc
|
||||
|
||||
svg.drag-gripper
|
||||
padding: 5px
|
||||
top: 7px
|
||||
left: 5px
|
||||
|
||||
input
|
||||
font-size: 1.36em
|
||||
color: black
|
||||
|
||||
svg.drag-gripper
|
||||
color: var(--color-strong)
|
||||
position: absolute
|
||||
padding: 8px
|
||||
top: 17px // Centered in 80px with 30px body and 8px padding
|
||||
left: 15px
|
||||
border-radius: 8px
|
||||
padding: 6px
|
||||
top: 14px // Centered in 64px with 24px body and 6px padding
|
||||
left: 12px
|
||||
cursor: grab
|
||||
|
||||
&::after
|
||||
width: 400px
|
||||
height: 20px
|
||||
width: 320px
|
||||
height: 64px
|
||||
content: ''
|
||||
position: absolute
|
||||
top: -20px
|
||||
top: -12px
|
||||
z-index: -1 // Prevent fluttering when moving mouse up
|
||||
|
||||
input
|
||||
padding: 20px
|
||||
margin: 0
|
||||
height: 40px
|
||||
padding: 0
|
||||
padding-top: 6px
|
||||
height: calc(100% - 6px)
|
||||
width: 100%
|
||||
background: none
|
||||
border: none
|
||||
text-align: center
|
||||
font-size: 2.6em
|
||||
width: 360px
|
||||
font-size: 2.1em
|
||||
|
||||
&:focus-visible
|
||||
border: none
|
||||
|
@ -96,12 +115,13 @@ input
|
|||
padding: 0
|
||||
text-align: center
|
||||
font-weight: bold
|
||||
font-size: 80px
|
||||
font-size: 64px
|
||||
color: white
|
||||
line-height: 0
|
||||
|
||||
#floaty-tile
|
||||
position: absolute
|
||||
pointer-events: none
|
||||
|
||||
&.hovering-1 > .tile
|
||||
--color-weak: #e5eed4
|
||||
|
@ -121,11 +141,29 @@ input
|
|||
|
||||
& > .tile
|
||||
position: relative
|
||||
top: -40px
|
||||
left: -40px
|
||||
pointer-events: none
|
||||
top: -32px
|
||||
left: -30px
|
||||
|
||||
// Disable selection while dragging a tile
|
||||
// broken on latest firefox tho
|
||||
body:has( > #floaty-tile)
|
||||
user-select: none
|
||||
--color-strong: #999
|
||||
--color-weak: #ccc
|
||||
|
||||
#word-bank
|
||||
width: calc(100% - 400px)
|
||||
padding: 30px 200px
|
||||
|
||||
display: flex
|
||||
flex-flow: row wrap
|
||||
justify-content: space-around
|
||||
|
||||
overflow-y: auto
|
||||
overflow-x: hidden
|
||||
|
||||
background-color: #eee
|
||||
|
||||
body
|
||||
user-select: none
|
||||
display: grid
|
||||
grid-template-rows: 1fr 20%
|
||||
height: 100%
|
||||
position: absolute
|
||||
margin: 0
|
Loading…
Reference in New Issue